Breaking Changes - Upgrade Guide

This guide lists all changes in ansible-oracle which require an action in your inventory, playbooks or environment when upgrading to a new major version.

How to use this guide:

  1. Find your current version and the target version.

  2. Read the overview table of every major version in between.

  3. Check the column Affected if against your inventory. Only the rows that match need an action.

Note
The complete list of changes is in CHANGELOG.rst. This guide only covers the changes from the section Breaking Changes / Porting Guide and explains the required actions.

1. Version 5.0.0

1.1. Overview

Change Affected if Action

Minimum ansible-core 2.16

ansible-core 2.14 or 2.15 is used on the controller or in the execution environment

Upgrade to ansible-core 2.16 or newer

Supported operating systems on target hosts

ansible-core 2.17 or newer and target hosts with Oracle Linux / RHEL 8 (Python 3.6)

Use ansible-core 2.16 for these hosts

Collection dependencies community.general and community.crypto

community.general < 11.0.0 or >= 12.0.0, or community.crypto >= 3.0.0 is installed or pinned in your requirements.yml

Use community.general 11.x and community.crypto 2.x

Strict boolean conditionals with ansible-core 2.19

ansible-core 2.19 or newer is used and your own playbooks or roles use variables directly in conditionals

Use | bool in your conditionals. ansible-oracle itself accepts strings like "yes" or -e var=false

Templating changes with ansible-core 2.19

ansible-core 2.19 or newer is used and your inventory contains templates ({% if %}, {{ }}) which create values for ansible-oracle

Check the result types of your templates

Default of oracle_sw_copy and oracle_sw_unpack with install_from_nfs

install_from_nfs: true and oracle_sw_copy or oracle_sw_unpack are not set in inventory

Set oracle_sw_copy: true and oracle_sw_unpack: true to keep the old behavior or test the installation directly from NFS

Firewall enabled by default on RHEL/OL

Target hosts with RHEL/OL and firewalld is installed and disable_firewall is not set in inventory

Check the permanent firewalld config before the upgrade, or set disable_firewall: true and firewall_open_listener_ports: false to keep the old behavior

Supported versions in db_homes_config

db_homes_config contains an ORACLE_HOME with a version other than 19.3.0.0 or 26.1.0.0

Upgrade the databases to 19c or 26ai, then remove the old ORACLE_HOMEs from db_homes_config. Emergency switch: assert_db_homes_config: false

python-oracledb replaces cx_Oracle

Always: the modules require python-oracledb instead of cx_Oracle on the target hosts. Action needed if the target hosts have no access to the Python package index, a proxy is needed (use_proxy, http_proxy), install_cx_oracle / cx_oracle_source / cx_oracle3_source / cx_oracle_umask are set in inventory or the role cxoracle is used in own playbooks

Set the new variables pyoracledb_wheel_dir, pyoracledb_use_proxy and pyoracledb_http_proxy, replace the role cxoracle by pyoracledb

oracle_job, oracle_directory, oracle_grants and oracle_privs: names in double quotes are case sensitive

A name of a profile, user, role, object or directory is enclosed in " by mistake (profiles and grants, object_privs, directory_privs of users in oracle_databases / oracle_pdbs, or the modules in own playbooks), or an existing profile, user, role or object has a name in lower or mixed case

Remove the " from the name, or write the name exactly as stored in the data dictionary in "

oracle_db uses hostname for the database connection

The listener does not listen on oracle_hostname (default: ansible_fqdn), or own playbooks use oracle_db with hostname / host

Set oracle_hostname to an address of the listener, this is also the way to use another listener address

Quotas for users in oracle_user and oradb_manage_users

quotas is set for a user (new option, without quotas no quota is removed or changed), or own playbooks use quotas from the old module PR ('<tablespace>:<size>')

No action without quotas, the quotas of the user are not changed. With quotas: add the default tablespace to quotas, if the user needs a quota there, and use the format {tablespace: <name>, size: <size>}

Internal variables of oraasm_manage_diskgroups removed

Own playbooks or inventories use the internal variables _oraasm_manage_diskgroups_attr_name or _oraasm_manage_diskgroups_attr_value

No action for inventories with asm_diskgroups. Otherwise use attributes of asm_diskgroups

Autostart of databases with one systemd unit per database and listener

autostartup_service: true on a Single Instance without Grid Infrastructure / Oracle Restart with systemd

No action for the new solution, it replaces oracle-rdbms.service with the next run of oradb_manage_db. A crashed database is restarted after 2 minutes, set autostartup_service_restart: false to disable it. Set autostartup_service_mode: legacy before the upgrade to keep the solution of 4.x

Autostart of databases is enabled by default

Single Instance without Grid Infrastructure / Oracle Restart and autostartup_service is not set in the inventory

No action, if the databases should start with the server. Otherwise set autostartup_service: false

init_parameters for one instance: sid and dbca

An entry in init_parameters of oracle_databases has an attribute sid other than *and dbca: true

Remove dbca: true from the entry. The parameter is set by oradb_manage_parameters after the creation of the database

oradb_rman: control_file_record_keep_time in init_parameters

A database in oracle_databases has rman_jobs and control_file_record_keep_time is missing in init_parameters or smaller than the days of RECOVERY WINDOW OF <n> DAYS

Add control_file_record_keep_time to init_parameters. Emergency switch: oradb_rman_assert_control_file_record_keep_time: false

oradb_rman: logfiles of rman_backup.sh

A database in oracle_databases has rman_jobs and the RMAN logfiles are monitored, evaluated or rotated (e.g. checkmk logwatch, logrotate, own scripts), or oradb_rman_cron_logdir / rman_cron_logdir is set

Change the monitoring to the new logfile names in RMAN_LOGDIR, remove oradb_rman_cron_logdir / rman_cron_logdir and the old logfiles

listener_installed with Grid Infrastructure / Oracle Restart: listener in its home

Grid Infrastructure / Oracle Restart and an entry in listener_installed with home

Use use_gi_home: true for a listener, which must stay in the GI / Oracle Restart home. Check the ORACLE_HOME of the listener resources (srvctl config listener)

local_listener in init_parameters of Single Instance databases

A Single Instance database (also with Oracle Restart) in oracle_databases with state: present has no local_listener in init_parameters

Add local_listener with EZConnect to init_parameters, e.g. {name: local_listener, value: '//localhost:1521', scope: both, state: present}. Emergency switch: orasw_meta_assert_oracle_databases: false (disables all asserts of oracle_databases)

oracle_databases: is_container and omf are true by default

A 19c database in oracle_databases without is_container (non-CDB) or without omf (created without OMF)

Set is_container: false for a new non-CDB. OMF is strongly recommended, omf: false needs an own DBCA template without OMF (dbca_templatename) and is not tested

oracle_databases: db_create_file_dest and db_recovery_file_dest in init_parameters

A database in oracle_databases with state: present and without omf: false and db_create_file_dest or db_recovery_file_dest is missing in init_parameters

Add db_create_file_dest and db_recovery_file_dest to init_parameters

oracle_databases: datafile_dest and recoveryfile_dest are removed

A database in oracle_databases with datafile_dest or recoveryfile_dest

Move the values to db_create_file_dest and db_recovery_file_dest in init_parameters and remove datafile_dest and recoveryfile_dest

oracle_dbf_dir_asm and oracle_reco_dir_asm removed

A database in oracle_databases with storage_type: ASM and omf: false, or oracle_dbf_dir_asm / oracle_reco_dir_asm are set in the inventory

Use OMF with ASM (db_create_file_dest and db_recovery_file_dest in init_parameters), remove oracle_dbf_dir_asm and oracle_reco_dir_asm

oracle_databases: max_pdbs in init_parameters of Container Databases

A Container Database (is_container: true, default) in oracle_databases with state: present and max_pdbs is missing in init_parameters or greater than 3 (SE2) / 1024 (EE)

Add max_pdbs with the number of PDBs allowed by your license to init_parameters, e.g. {name: max_pdbs, value: '3', scope: both, state: present}. EE: more than 3 PDBs only with a license for the Multitenant Option

oracle_databases: control_management_pack_access in init_parameters of Enterprise Edition databases

A database of an Enterprise Edition home in oracle_databases with state: present and control_management_pack_access is missing in init_parameters or has a value other than NONE, DIAGNOSTIC or DIAGNOSTIC+TUNING, or a database of a Standard Edition 2 home with a value other than NONE

Add control_management_pack_access with the value allowed by your license to init_parameters, e.g. {name: control_management_pack_access, value: 'NONE', scope: both, state: present}

oracle_databases: sga_target and pga_aggregate_target in init_parameters

A database in oracle_databases with state: present and sga_target or pga_aggregate_target is missing in init_parameters, or oracle_db_mem_totalmb is set

Add sga_target and pga_aggregate_target to init_parameters, remove oracle_db_mem_totalmb

oracle_databases: no memory_target and memory_max_target with Hugepages

A database in oracle_databases with state: present and memory_target or memory_max_target in init_parameters and configure_hugepages is not false

Replace memory_target / memory_max_target by sga_target and pga_aggregate_target (state: absent for the old parameters), or set configure_hugepages: false

oracle_databases: processes in init_parameters

A database in oracle_databases with state: present and processes is missing in init_parameters

Add processes to init_parameters, e.g. {name: processes, value: '640', scope: spfile, state: present}. Usually irrelevant in practice, the default of processes is too small in most cases anyway

Role oraswahf_install replaced by ahf

Own playbooks use the role oraswahf_install

Use the new role ahf (playbook opitzconsulting.ansible_oracle.ahf)

Default of oracle_install_version_gi is 26ai

oracle_install_option_gi is HA_CONFIG or CRS_CONFIG and oracle_install_version_gi is not set in inventory

Set oracle_install_version_gi to the base release of the installation media, e.g. 19.3.0.0 for 19c. Usually irrelevant in practice, the version must match the installation media anyway

1.2. Minimum ansible-core 2.16

ansible-oracle 5.x supports ansible-core 2.16 - 2.19. ansible-oracle 4.x supports ansible-core 2.14 - 2.18, so ansible-core 2.19 requires ansible-oracle 5.x.

ansible-oracle ansible-core

4.x

2.14 - 2.18

5.x

2.16 - 2.19

The minimum version is defined by requires_ansible in meta/runtime.yml and min_ansible_version in meta/main.yml of all roles.

Check the version on the controller or in your execution environment:

ansible --version

1.2.1. Python on controller and target hosts

Each ansible-core version supports a fixed range of Python versions on the controller and on the target hosts:

ansible-core Python on controller Python on target host

2.16

3.10 - 3.12

2.7, 3.6 - 3.12

2.17

3.10 - 3.12

3.7 - 3.12

2.18

3.11 - 3.13

3.8 - 3.13

2.19

3.11 - 3.13

3.8 - 3.13

The Python on the target host is the system Python or the interpreter from ansible_python_interpreter.

1.2.2. Supported operating systems on target hosts

OS System Python ansible-core 2.16 ansible-core 2.17 - 2.19

Oracle Linux / RHEL 8

3.6

yes

no - see below

Oracle Linux / RHEL 9

3.9

yes

yes

Oracle Linux / RHEL 10

3.12

yes

yes

SLES / openSUSE Leap 15

3.6

yes

only with python311 (SLES 15 SP4 or newer) and ansible_python_interpreter: /usr/bin/python3.11 - not tested with ansible-oracle

Important
Use ansible-core 2.16 for Oracle Linux / RHEL 8.
The system Python 3.6 is not supported by ansible-core 2.17 or newer, even fact gathering fails. A newer Python from AppStream (e.g. python3.12 with ansible_python_interpreter: /usr/bin/python3.12) runs most modules, but ansible.builtin.dnf and ansible.builtin.yum fail, because the dnf Python bindings exist for Python 3.6 only: Could not import the dnf python module using /usr/bin/python3.12. The roles common, orahost, oraords and oraswgi_install install packages with these modules. Tested with ansible-core 2.19.14 and Oracle Linux 8.10.

The controller can use another OS than the target hosts. Oracle Linux 8 and 9 provide Python 3.11 and 3.12 as additional packages (python3.11, python3.12) for a controller with ansible-core 2.19.

1.3. Collection dependencies community.general and community.crypto

The dependencies in galaxy.yml are limited to versions, which support the minimum ansible-core version and Python 3.6 on the target hosts:

Collection 4.x 5.0.0

community.general

>=8.6.0

>=11.0.0,<12.0.0

community.crypto

>=2.21.1

>=2.21.1,<3.0.0 (3.x needs ansible-core >= 2.17)

ansible-galaxy collection install fails with a dependency conflict, when your requirements.yml pins a version outside of these ranges. Remove the pinning or adjust it to the ranges above.

1.4. Strict boolean conditionals with ansible-core 2.19

ansible-core 2.19 requires a real boolean as result of a conditional (when, failed_when, changed_when, until, assert: that). Older versions converted strings like "false" or "yes" silently. Now the task fails:

Conditional result (True) was derived from value of type 'str' at '...'. Conditionals must have a boolean result.

ansible-oracle 5.0.0 evaluates all boolean variables from the inventory with | bool. Strings like "true", "yes", "false" or extra-vars like -e oracle_sw_copy=false work as before.

Your own playbooks and roles are affected, when they use variables directly in conditionals:

# fails with ansible-core 2.19, when my_flag is a string ("true", "yes", -e my_flag=true)
when: my_flag

# works with all versions
when: my_flag | bool

The bool filter accepts true/false, yes/no, on/off, 1/0 (case-insensitive). Other values (e.g. "enabled" or an empty string) result in a deprecation warning and false. This will be an error in ansible-core 2.23.

Tip
ANSIBLE_ALLOW_BROKEN_CONDITIONALS=true restores the old behavior temporarily. Use it only to find the affected conditionals, not as permanent solution.

1.5. Templating changes with ansible-core 2.19

ansible-core 2.19 has a new templating engine. The result of a template has a different type in some cases. ansible-oracle 5.0.0 is adapted, but templates in your inventory are used as they are.

Template ansible-core < 2.19 ansible-core 2.19

"{% if x %}True{% else %}False{% endif %}"

bool

string "True" / "False"

"{% if x %}{'key': 1}{% endif %}", "{% if x %}[1, 2]{% endif %}"

dict / list

string

"{% if x %}-flag{% endif %}" with x false (empty result)

empty string ""

None

"{{ 1521 }}"

string "1521"

int 1521

Examples of failing expressions with ansible-core 2.19:

my_flag: "{% if foo %}True{% else %}False{% endif %}"
my_param: "{% if foo %}-flag{% endif %}"
my_port: "{{ 1521 }}"

# when: my_flag              -> fails: string instead of boolean
# when: my_param == ''       -> false, because the value is None
# "{{ my_param | length }}"  -> fails: None has no length
# "{{ 'host:' + my_port }}"  -> fails: string + int
# when: my_port == '1521'    -> false, because the value is an int

Recommendations:

  • Write expressions instead of text: my_flag: "{{ foo | bool }}" or my_flag: "{{ foo == 'x' }}".

  • Use YAML for lists and dictionaries instead of creating them as text.

  • Use | default('', true) when a template can be empty and a string is needed.

  • Use | int or | string for comparisons.

An empty template in environment: sets the environment variable to the text None, e.g. _JAVA_OPTIONS=None lets Java fail with Unrecognized option: None. Use "{{ my_value | default('', true) }}" for environment variables, which can be empty.

Embedding these values into other strings is not affected: "gridSetup.sh {{ my_param }}" renders an empty string for None in all versions.

1.6. Other ansible-core 2.19 changes for own playbooks and inventories

ansible-oracle 5.0.0 is checked for these changes. They are relevant for your own playbooks, inventories and ansible.cfg:

  • File modes must be quoted strings in inventories: mode: '0775' instead of mode: 775. An unquoted 775 is an integer and is passed through templates (for example mode: "{{ item.mode }}") as decimal 775, which is mode 1407. Before 2.19 the template converted the value to the string "775", which was interpreted as octal.

  • with_nested handles strings differently (not mentioned in the porting guide): an empty string "" is an empty list (the task is skipped completely), a templated string "{{ var }}" is split into single characters. Use lists: - [""] or - ["{{ var }}"].

  • A loop over an undefined list fails, although when is false, when delegate_to uses the loop variable (not mentioned in the porting guide). Use loop: "{{ my_list | default([]) }}".

  • Templates inside conditionals fail: that: swap >= {{ min_swap }} must be written as that: swap >= min_swap | int.

  • The ssh connection uses SSH_ASKPASS instead of sshpass for password authentication. Set password_mechanism = sshpass in section [ssh_connection] of ansible.cfg to keep the old behavior.

  • The bool filter warns for values other than true/false, yes/no, on/off, 1/0 (and None). This will be an error in ansible-core 2.23.

  • A timeout of become is an unreachable error. Use ignore_unreachable instead of ignore_errors.

  • The magic variable play_hosts is deprecated, use ansible_play_batch.

The complete list is in the ansible-core 2.19 Porting Guide.

1.7. Default of oracle_sw_copy and oracle_sw_unpack with install_from_nfs

The defaults of oracle_sw_copy and oracle_sw_unpack depend on install_from_nfs. Until 4.x the defaults were the strings "true" or "false". The string "false" is not empty and was evaluated as true in most conditionals. The documented behavior for install_from_nfs: true (no copy, no unpack) was therefore not active, unless both variables were set explicitly in the inventory.

As of 5.0.0 both defaults are real booleans.

install_from_nfs: true and …​ 4.x 5.0.0

oracle_sw_copy/oracle_sw_unpack not set

installation media are copied and unpacked to oracle_stage

installation media are used from oracle_stage_remote (NFS mount)

oracle_sw_copy/oracle_sw_unpack set as boolean

no change

no change

Affected variables with changed default value: oracle_sw_copy, oracle_sw_unpack, oracle_stage_install, oracle_patch_install.

Keep the behavior of 4.x:

install_from_nfs: true
oracle_sw_copy: true
oracle_sw_unpack: true

1.8. Firewall enabled by default on RHEL/OL

Until 4.x the role orahost stopped and disabled firewalld on RHEL/OL by default (disable_firewall: true). As of 5.0.0 firewalld stays active and the role opens the ports of the Oracle listeners:

Variable 4.x 5.0.0

disable_firewall

true

false

firewall_open_listener_ports

- (not available)

true (new)

The change applies only to RHEL/OL target hosts with installed firewalld. SUSE is not changed.

What orahost does with the new defaults:

  1. Checks, if the permanent firewalld config allows the SSH connection of Ansible (service ssh, port and target of the zone). The play fails, when starting firewalld would block SSH. Rich rules and zones bound to sources are not evaluated by this check.

  2. Starts and enables firewalld.

  3. Opens the following TCP ports in the permanent and the running config:

    • all ports from address in oracle_listeners_config with a host (IPC addresses are ignored, listener_port is used for addresses without port),

    • all ports from the new variable oracle_extra_firewall_ports,

    • oracle_scan_port with oracle_install_option_gi: CRS_CONFIG.

Other ports are not opened automatically, e.g. EM Express (5500), ORDS/APEX or the Enterprise Manager agent. Add them to oracle_extra_firewall_ports:

oracle_extra_firewall_ports:
  - 5500  # EM Express
Warning
Oracle RAC needs unrestricted network traffic on the private interconnect. Allow the interconnect in firewalld (for example with a trusted zone for the interconnect interfaces) or set disable_firewall: true on the cluster nodes.

Combinations of both variables:

disable_firewall firewall_open_listener_ports Result

false

true

Default in 5.0.0: firewalld is started and enabled, ports are opened immediately and permanently

true

false

Behavior of 4.x: firewalld is stopped and disabled

true

true

firewalld is stopped and disabled, ports are only added to the permanent config (prepared for a later start)

false

false

firewalld is not changed by orahost

Keep the behavior of 4.x:

disable_firewall: true
firewall_open_listener_ports: false

1.9. Supported versions in db_homes_config

The role orasw_meta checks db_homes_config. It is a dependency of nearly all roles, so the check runs in nearly every playbook. As of 5.0.0 only Oracle 19c and 26ai are accepted as version:

Version Allowed version in db_homes_config

4.x

26.1.0.0, 21.3.0.0, 19.3.0.0, 18.3.0.0, 12.2.0.1, 12.1.0.2, 11.2.0.4, 11.2.0.3

5.0.0

26.1.0.0, 19.3.0.0

version is the base release of the ORACLE_HOME. Release Updates are not part of it, e.g. an ORACLE_HOME with 19.32 uses version: 19.3.0.0.

An ORACLE_HOME with another version stops the playbook with a failed assert, even when the ORACLE_HOME is not used by the playbook. Upgrade the databases to 19c or 26ai, e.g. with the role autoupgrade, and remove the old ORACLE_HOMEs from db_homes_config afterwards.

The assert can be disabled in emergency cases:

assert_db_homes_config: false
Warning
assert_db_homes_config: false disables all checks of db_homes_config, not only the check of the version. Missing oracle_home, edition or opatch_minversion are no longer detected. ORACLE_HOMEs with other versions are not tested with ansible-oracle 5.x.

1.10. python-oracledb replaces cx_Oracle

python-oracledb (Python package oracledb) is the successor of cx_Oracle. All modules of ansible-oracle are migrated from cx_Oracle to python-oracledb. cx_Oracle is no longer used.

The new role pyoracledb installs python-oracledb with pip3 on the target hosts. The playbook os.yml executes pyoracledb instead of cxoracle.

Important
The role cxoracle and its variables are removed. Variables like install_cx_oracle or cx_oracle_source in the inventory have no effect anymore. Own playbooks using the role opitzconsulting.ansible_oracle.cxoracle fail, replace it by opitzconsulting.ansible_oracle.pyoracledb. cx_Oracle is not removed from existing target hosts.

The modules require python-oracledb on the target hosts instead of cx_Oracle. python-oracledb is used in thick mode, so the Oracle Client libraries must be found (ORACLE_HOME and LD_LIBRARY_PATH), like with cx_Oracle before.

Migrated modules:

  • oracle_asmdg

  • oracle_asmvol

  • oracle_awr

  • oracle_db

  • oracle_directory

  • oracle_facts

  • oracle_grants

  • oracle_job

  • oracle_jobclass

  • oracle_jobschedule

  • oracle_jobwindow

  • oracle_ldapuser

  • oracle_parameter

  • oracle_pdb

  • oracle_privs

  • oracle_profile

  • oracle_redo

  • oracle_role

  • oracle_rsrc_consgroup

  • oracle_services (python-oracledb is only used without Grid Infrastructure)

  • oracle_sql

  • oracle_stats_prefs

  • oracle_tablespace

  • oracle_user

The role pyoracledb installs a fixed version of python-oracledb, depending on the Python version of the target host (ansible_python_interpreter, needs gather_facts):

Python on the target host Variable Default

3.6 (Oracle Linux / RHEL 8, SLES 15)

pyoracledb_version_py36

1.4.2

3.7

pyoracledb_version_py37

2.3.0

3.8

pyoracledb_version_py38

3.0.0

3.9 (Oracle Linux / RHEL 9)

pyoracledb_version_py39

4.0.2

all other versions

pyoracledb_version

26.1.0 (updated by renovate)

Without changes in the inventory, pyoracledb installs this version from the Python package index (pip install oracledb==<version>). The installation fails, when the target hosts have no access to the package index.

The wheel files of python-oracledb need pip 19.3 or newer (manylinux2014). The system pip of Oracle Linux / RHEL 8 is 9.0.3, it would try to build python-oracledb from source, which fails. Therefore pyoracledb installs pip>=19.3 first, if pip is older (Python 3.6: pip 21.3.1 in /usr/local).

The role pyoracledb uses own variables with the prefix pyoracledb_. The variables of the removed role cxoracle are not used by pyoracledb, even use_proxy, http_proxy and extra_args:

cxoracle pyoracledb Description

install_cx_oracle

pyoracledb_install

Install the package? Default: true

cx_oracle_source, cx_oracle3_source

pyoracledb_wheel_dir (and pyoracledb_version*)

Directory with wheel files instead of a single package or file. Default: package index

cx_oracle_umask

pyoracledb_umask

umask for the pip installation

use_proxy

pyoracledb_use_proxy

Use a proxy for the pip installation. Default: false

http_proxy

pyoracledb_http_proxy

Proxy for the pip installation

extra_args

pyoracledb_extra_args

Additional arguments for pip, e.g. --index-url=…​ for an internal mirror. The default contains the proxy and the client certificates get_url_ssl_client_cert / get_url_ssl_client_key

cx_oracle_source / cx_oracle3_source pointed to one package or file. pyoracledb_wheel_dir points to a directory with wheel files of python-oracledb, pip selects the file matching the Python version (pip install --no-index --find-links <pyoracledb_wheel_dir> oracledb==<version>). One directory can contain the wheel files for all Python versions of the target hosts (e.g. cp36 and cp39):

  • local directory on the Ansible controller, copied to <oracle_stage>/pyoracledb when is_sw_source_local: true and oracle_sw_copy: true. With oracle_sw_copy: false the directory must exist on the target host (e.g. NFS).

  • URL (http://, https://) of a page with links to the wheel files, used directly by pip

use_proxy, http_proxy and extra_args can be kept in the inventory, if they are used for other purposes.

Example of the migration of the inventory:

# before (cxoracle)
cx_oracle_source: "file:///sw/cx_Oracle-8.3.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl"
use_proxy: true
http_proxy: proxy.example:3128

# after (pyoracledb)
pyoracledb_wheel_dir: /sw/python-oracledb
pyoracledb_use_proxy: true
pyoracledb_http_proxy: proxy.example:3128

Download the wheel files for the target hosts on a host with access to the package index, one command per Python version with the matching version from the table above:

pip download --no-deps --only-binary=:all: --python-version 3.6 \
  --platform manylinux2014_x86_64 -d /sw/python-oracledb oracledb==1.4.2
# pip for Python 3.6 (the system pip of OL8 is too old for the wheel files)
pip download --no-deps --only-binary=:all: --python-version 3.6 \
  -d /sw/python-oracledb pip==21.3.1
pip download --no-deps --only-binary=:all: --python-version 3.9 \
  --platform manylinux2014_x86_64 -d /sw/python-oracledb oracledb==4.0.2

Skip the installation of python-oracledb:

pyoracledb_install: false

1.11. oracle_profile, oracle_job, oracle_directory, oracle_grants and oracle_privs: names in double quotes are case sensitive

The modules oracle_profile, oracle_job, oracle_directory, oracle_grants and oracle_privs handle names like SQL (ANSI): a name in double quotes (") is case sensitive, a name without quotes is converted to uppercase. All other modules are not changed. The functions for this are in plugins/module_utils/oracle_identifier.py and can be used by more modules in the future. Such a change will be listed here.

Module Before Now

oracle_profile

The name was not quoted in the SQL statements, but compared case insensitive with DBA_PROFILES. A name in " was created case sensitive, but not found in the next run (ORA-02379).

A name in " is used case sensitive, e.g. name: '"Gestion/Monitorizacion"'. A name without " is used in uppercase and compared exactly with DBA_PROFILES.

oracle_job

A job_name with " failed with Invalid job name.

A part of job_name in " is case sensitive, e.g. job_name: 'SYSTEM."My_Job"'. convert_to_upper works as before for parts without ".

oracle_directory

The name was not quoted in the SQL statements and compared in uppercase with DBA_DIRECTORIES. A name in " was created case sensitive, but not found in the next run (ORA-00955).

A name in " is used case sensitive, e.g. directory_name: '"MyDir"'. "MyDir" and MYDIR are two different directories. A name without " is used in uppercase as before.

oracle_grants

The grantee (schema, role) was compared in uppercase, roles and objects in grants and object_privs were compared case insensitive, but not quoted in the SQL statements. A grantee or object in " was not found. Granting or revoking a privilege on an object with a lower or mixed case name failed (ORA-00942). With state: absent the names in grants had to be in lowercase. directory_privs needed sys.<directory>.

Grantee, roles in grants, owner and object in object_privs and the directory in directory_privs can be in " (case sensitive), e.g. schema: '"MyUser"', grants: ['"MyRole"'], object_privs: ['select:"MyOwner"."MyTable"']. Names without " are used in uppercase and compared exactly. state: absent compares in any case. An object without owner is in the current schema of the connection, sys. is optional for directories.

oracle_privs

Names with " failed with Invalid privilege, Invalid user/role or Invalid object. convert_to_upper was valid for all names in roles and objs. A role in privs was always converted to uppercase.

A name in " is case sensitive in roles, objs (owner and object, also with the wildcard %) and for a role in privs, e.g. roles: ['"MyUser"'], objs: ['"MyOwner".%'], privs: ['"MyRole"']. convert_to_upper works as before for names without ". No action needed, names without " are handled as before.

PDB names are not affected: Oracle stores them always in uppercase, oracle_pdb converts the name to uppercase as before.

For most inventories nothing changes, because names without " are stored in uppercase as before.

Important
Check names which are enclosed in " by mistake, e.g. from a copied SQL statement. They are case sensitive now and refer to a different object than before, so the module creates a new profile or directory with the exact name, or grants a privilege on a different object or role. The roles of ansible-oracle do not use oracle_directory, so only own playbooks are affected for directories.

An existing profile with a name in lower or mixed case (created outside of ansible-oracle) was found before with a name in any case. Now the name must be given exactly in ", otherwise the module creates a new profile in uppercase.

The same applies to oracle_grants: a grant on an existing object or role with a lower or mixed case name, which was found before with a name in any case, must be given exactly in ". Otherwise the module tries to grant the privilege on the uppercase name (ORA-00942 or ORA-01919) and, with grants_mode: enforce, revokes the existing grant.

Find objects and roles with a name in lower or mixed case
select owner, object_name, object_type from dba_objects where object_name <> upper(object_name) or owner <> upper(owner);
select role from dba_roles where role <> upper(role);
Find profiles with a name in lower or mixed case
select distinct profile from dba_profiles where profile <> upper(profile);
Profile with a mixed case name in the inventory
oracle_pdbs:
  - cdb: DB1
    pdb_name: ORCLPDB
    profiles:
      # before: MyProfile was found case insensitive
      # - name: MyProfile
      - name: '"MyProfile"'
        state: present
        attributes:
          - {name: password_life_time, value: unlimited}

1.12. oracle_db uses hostname for the database connection

This is a bugfix (#542), but it changes the address used for the database connection.

oracle_db ignored the option hostname (alias host) and always connected to the local host name (os.uname()[1]). This forced a listener on that address, which is not allowed in all environments. Now oracle_db connects to hostname, without hostname to os.uname()[1] as before.

The roles oradb_manage_db, oradb_manage_parameters and oradb_datapatch pass oracle_hostname as hostname, like all other oradb_manage_* roles already do. oracle_hostname defaults to ansible_fqdn, so all roles connect to ansible_fqdn unless oracle_hostname is set in inventory.

For most inventories nothing changes, because the other oradb_manage_* roles already need a listener on oracle_hostname.

Use another listener address
# default: ansible_fqdn
oracle_hostname: dbhost-lsnr.example.com
Note
oracle_hostname is also used as host name in the RDBMS installation and as node name for Grid Infrastructure.
Important
An explicit hostname: localhost for oracle_db in own playbooks was ignored before. Now the module connects to localhost, which works only, if the listener listens on this address. Remove hostname to keep the old behavior.

1.13. Quotas for users in oracle_user and oradb_manage_users

This is a new feature (#312), not a breaking change.

Note
Without quotas no quota is removed or changed, the existing quotas of a user are kept. quotas_mode has no effect without quotas. A user with default_tablespace gets QUOTA UNLIMITED on this tablespace as before.

Quotas are only removed, if the inventory says so: with size: 0 for a tablespace in quotas, or with quotas_mode: enforce for all tablespaces not in quotas.

oracle_user and the users of oracle_databases / oracle_pdbs (role oradb_manage_users) have two new options:

  • quotas: list of tablespace and size. size is the number of bytes with an optional unit K, M, G, T, P, E or unlimited. size: 0 removes the quota on the tablespace.

  • quotas_mode: append (default) changes only the tablespaces in quotas, enforce removes all other quotas of the user.

Important
With quotas, the default tablespace gets no automatic QUOTA UNLIMITED. Add the default tablespace to quotas, if the user needs a quota there. An existing quota on the default tablespace is kept with quotas_mode: append, but removed with quotas_mode: enforce, if the tablespace is not in quotas.

Oracle rounds a quota up to whole blocks of the tablespace, e.g. size: 1000 is stored as 8192 bytes with a block size of 8K. The comparison uses blocks, so the module is idempotent for such sizes.

User with quotas, all other quotas are removed
oracle_pdbs:
  - cdb: orcl
    pdb_name: ORCLPDB
    users:
      - schema: app
        state: present
        default_tablespace: app_data
        quotas_mode: enforce
        quotas:
          # without this entry, app has no quota on its default tablespace
          - tablespace: app_data
            size: unlimited
          - tablespace: app_index
            size: 500M
Note
The old pull request for quotas in ansible-oracle-modules (#158) used a list of strings '<tablespace>:<size>'. This format is not supported, use {tablespace: <name>, size: <size>}.

1.14. Internal variables of oraasm_manage_diskgroups removed

This is not a breaking change for inventories, the variables were internal (prefix _). It is listed here for own playbooks or roles which used them.

The role oraasm_manage_diskgroups built the attributes for oracle_asmdg in the variables _oraasm_manage_diskgroups_attr_name and _oraasm_manage_diskgroups_attr_value. For a disk group without attributes they contained the string None, which was passed to oracle_asmdg as attribute (#491). The variables are removed, the role passes attributes of asm_diskgroups directly to oracle_asmdg, a disk group without attributes gets no attributes.

Note
No action is needed for inventories with asm_diskgroups, attributes works as before.
Attributes of a disk group
asm_diskgroups:
  - diskgroup: data
    state: present
    attributes:
      - {name: compatible.asm, value: 19.0.0.0.0}
      - {name: compatible.rdbms, value: 19.0.0.0.0}
    disk:
      - {device: /dev/sdb, asmlabel: data01}

1.15. Autostart of databases with one systemd unit per database and listener

The autostart with autostartup_service: true (Single Instance without Grid Infrastructure / Oracle Restart) uses new systemd units (#265). The solution of 4.x is still available with autostartup_service_mode: legacy.

The service oracle-rdbms.service of 4.x had some problems:

  • systemd killed a database after 90 seconds, when shutdown immediate took longer (default timeout, KillMode=control-group).

  • A database without ~/.profile_<ORACLE_SID> was not shut down, but killed by systemd.

  • A database started outside of systemd (e.g. with sqlplus in a ssh session) was killed with the session during a shutdown of the server.

  • Remote file systems (e.g. NFS) could be unmounted before the database was stopped.

  • A failed start of a database was not reported, the service was active.

4.x (autostartup_service_mode: legacy) 5.x (autostartup_service_mode: units, default)

Units

oracle-rdbms.service for all databases in /etc/oratab, created by oraswdb_install

oracle-db@<ORACLE_SID>.service per database from oracle_databases and oracle-listener@<LISTENER_NAME>.service per listener from listener_installed (or listener_name of oracle_databases), grouped by oracle-databases.target and oracle-listeners.target, created by oradb_manage_db

Start/stop script

/usr/local/bin/manage_oracle_rdbms_procs.sh, listener from ~/.profile_<ORACLE_SID>

/usr/local/bin/oracle-systemd, environment in /etc/sysconfig/oracledb/db-<ORACLE_SID> and /etc/sysconfig/oracledb/listener-<LISTENER_NAME>

Timeouts

systemd default (90 seconds), then the database is killed

autostartup_service_start_timeout / autostartup_service_stop_timeout (default 15min), systemd never kills a database (KillMode=process)

Databases started outside of systemd

killed during a shutdown of the server

attached to their unit by oracle-adopt.timer (autostartup_service_adopt_interval, systemd API AttachProcessesToUnit) and at the start of the unit

Dependencies

autostartup_service_dependency (default network.target) in Requires= and After=

autostartup_service_dependency in Requires= and After= of all units, After=network-online.target remote-fs.target local-fs.target is always set

Start of a single database

not possible

systemctl start oracle-db@<ORACLE_SID>

Crash of a database

not detected, the service stays active

The unit monitors PMON. After a crash (no Instance shutdown complete / Instance shutdown (abort) complete in the alert log) systemd restarts the database after autostartup_service_restart_sec (default 2min), see Restart of a database after a crash. A shutdown in sqlplus is not restarted, the unit is inactive.

ORACLE_HOME of a database

from /etc/oratab

from /etc/oratab (start), from the running instance (stop)

The migration is done by the next run of oradb_manage_db (playbook manage_db.yml). The databases and listeners are not restarted: the new units are started and attach the running databases and listeners. oracle-rdbms.service is disabled. Its unit file is removed, when the service is inactive, otherwise in the first run after the next reboot. An active service without unit file would be stopped without its stop script during a shutdown.

1.15.1. Restart of a database after a crash

This is new behavior compared to 4.x: oracle-rdbms.service did not detect a crash, a crashed database stayed down until it was started manually.

The unit oracle-db@<ORACLE_SID>.service monitors PMON of the database every 10 seconds. When PMON is gone, the last entry in the alert log decides:

Last entry in the alert log Unit

Instance shutdown complete or Instance shutdown (abort) complete (shutdown in sqlplus, also shutdown abort)

inactive, no restart. The unit is started again by oracle-adopt.timer, when the database is started in sqlplus.

other entry, e.g. Instance terminated by …​ (crash)

autostartup_service_restart: true (default): restart after autostartup_service_restart_sec (default 2min), max. 10 starts of the unit within 1 hour. autostartup_service_restart: false: failed, no restart.

autostartup_service_restart can be set for all databases or per database in oracle_databases. A change is used by the next run of oradb_manage_db without a restart of the database.

Restart after a crash only for DB1
autostartup_service_restart: false

oracle_databases:
  - oracle_db_name: DB1
    autostartup_service_restart: true
    ...
Important
Check the restart, when a database must not start automatically after a crash, e.g. because a crash is analyzed before the restart or another tool restarts the database.
Important
Set autostartup_service_mode: legacy in the inventory before the upgrade to 5.x to keep the solution of 4.x. oraswdb_install creates oracle-rdbms.service as before and oradb_manage_db does not create the new units.
Keep the autostart of 4.x
autostartup_service: true
autostartup_service_mode: legacy

A switch from units back to legacy removes the new units in the next run of oradb_manage_db (the databases are not stopped). Active units are disabled and their unit files are removed in the first run after the next reboot. Run oraswdb_install (playbook swdb.yml) to create oracle-rdbms.service again.

Note
dbora for init (EL6) is not changed. Restart the databases with systemctl restart oracle-db@<ORACLE_SID> instead of sqlplus, then the database is always in its unit.

1.16. Autostart of databases is enabled by default

The default of autostartup_service is true since 5.0.0 (4.x: false). A Single Instance without Grid Infrastructure / Oracle Restart gets the autostart of the databases and listeners with the next run of oraswdb_install and oradb_manage_db, when autostartup_service is not set in the inventory. The solution is selected with autostartup_service_mode, see Autostart of databases with one systemd unit per database and listener.

autostartup_service is not used with Grid Infrastructure / Oracle Restart, the databases are started by the Clusterware.

The databases are written with the flag Y into /etc/oratab (as before with autostartup_service: true).

Keep the behavior of 4.x without autostart
autostartup_service: false

1.17. init_parameters for one instance: sid and dbca

init_parameters in oracle_databases and oracle_pdbs support the new attribute sid (#677). It is the SID clause of ALTER SYSTEM SET, e.g. for local_listener per RAC instance. Without sid or with sid: '*' the parameter is set for all instances as before.

dbca has no SID clause for initialization parameters. A parameter for one instance would be set for all instances during the creation of the database. Therefore sid other than * together with dbca: true is not allowed, the assert of oracle_databases in orasw_meta fails. Entries with sid and without dbca are not passed to dbca (default dbca: false for these entries), they are set by oradb_manage_parameters after the creation of the database.

Note
sid is case-sensitive like the SID clause of ALTER SYSTEM, use the instance name exactly as in V$INSTANCE.INSTANCE_NAME.
Not allowed
oracle_databases:
  - oracle_db_name: orcl
    init_parameters:
      - {name: local_listener, value: 'rac1-vip:1521', scope: both, state: present, sid: orcl1, dbca: true}
local_listener per instance
oracle_databases:
  - oracle_db_name: orcl
    init_parameters:
      - {name: local_listener, value: 'rac1-vip:1521', scope: both, state: present, sid: orcl1}
      - {name: local_listener, value: 'rac2-vip:1521', scope: both, state: present, sid: orcl2}

1.18. oradb_rman: control_file_record_keep_time in init_parameters

control_file_record_keep_time defines, how many days the controlfile keeps the records of backups. Without RMAN catalog, RMAN knows only the backups in the controlfile: a value smaller than the recovery window makes backups unusable for RMAN, although they exist.

As of 5.0.0 oradb_rman asserts for every database with rman_jobs:

  • control_file_record_keep_time is defined in init_parameters (state: present, sid: '*'), and

  • the value is >= <n> for the retention policy RECOVERY WINDOW OF <n> DAYS (rman_retention_policy of the database or oradb_rman_retention_policy_default).

The playbook stops with a failed assert, when the parameter is missing or too small.

Example for RECOVERY WINDOW OF 14 DAYS
oracle_databases:
  - oracle_db_name: DB1
    rman_retention_policy: 'RECOVERY WINDOW OF 14 DAYS'
    init_parameters:
      - {name: control_file_record_keep_time, value: '30', scope: both, state: present}
    rman_jobs:
      - {name: parameter}

The assert can be disabled in emergency cases:

oradb_rman_assert_control_file_record_keep_time: false

1.19. oradb_rman: logfiles of rman_backup.sh

The logging of rman_backup.sh and of the RMAN cron jobs was rebuilt. Before 5.0.0 the output was written into two growing files per job, which mixed the output of parallel executions and were only cleaned up by an external logrotate (e.g. orahost_logrotate).

Table 1. Logfiles before and as of 5.0.0
Before 5.0.0 As of 5.0.0

Cron output

<oradb_rman_cron_logdir>/rman_<oracle_db_name>_<job>.log (default /var/log/oracle/rman/log), appended

/dev/null: rman_backup.sh writes all output into its own logfile

Logfile of rman_backup.sh

<RMAN_LOGDIR>/<ORACLE_SID>_<action>.log, output of RMAN only, appended

<RMAN_LOGDIR>/<db_unique_name>_<action>_<YYYYmmdd>_<HHMMSS>_<pid>.log, one file per execution with the output of the script, sqlplus and RMAN

Last execution

-

Symlink <RMAN_LOGDIR>/<db_unique_name>_<action>.log to the logfile of the last execution

Cleanup

-

Logfiles older than oradb_rman_log_retention days (default 30, RMAN_LOG_RETENTION in rman_backup.cfg) are removed by rman_backup.sh

Parallel executions of the same action

executed, output mixed in one logfile

The 2nd execution stops with exit code 30 (lock file <RMAN_LOGDIR>/.<db_unique_name>_<action>.lock)

Changes in detail:

  • oradb_rman_cron_logdir and rman_cron_logdir are removed. The directory /var/log/oracle/rman/log is no longer created or written.

  • The prefix of the logfile is the db_unique_name instead of the ORACLE_SID. The name changes for every database with db_unique_name != ORACLE_SID, e.g. Data Guard or RAC.

  • The 1st execution renames an existing logfile <RMAN_LOGDIR>/<db_unique_name>_<action>.log of older versions to *.log.old and creates the symlink with this name.

  • Manual executions write the same logfiles as the cron jobs.

Who is affected:

  • Monitoring of the logfiles (e.g. checkmk logwatch, own scripts), which reads /var/log/oracle/rman/log/* or <RMAN_LOGDIR>/<ORACLE_SID>_<action>.log.

  • Monitoring of the exit code (e.g. mk-job): exit code 30 for a 2nd execution of a running action is new.

  • logrotate rules for the RMAN logfiles, e.g. the default of orahost_logrotate: rman_backup.sh removes old logfiles itself, logrotate must not rotate the logfiles with timestamp (logrotate refuses to rotate the symlink).

Required actions:

  1. Remove oradb_rman_cron_logdir and rman_cron_logdir from the inventory.

  2. Change the monitoring to the symlink <RMAN_LOGDIR>/<db_unique_name>_<action>.log or to the logfiles with timestamp.

  3. Remove logrotate rules for RMAN_LOGDIR and set oradb_rman_log_retention instead.

  4. Remove the old logfiles after the upgrade, when they are not needed anymore:

    rm -r /var/log/oracle/rman/log
    rm <RMAN_LOGDIR>/*.log.old

1.20. listener_installed with Grid Infrastructure / Oracle Restart: listener in its home

With Grid Infrastructure or Oracle Restart oradb_manage_db registers every listener of listener_installed with srvctl add/modify listener (module oracle_crs_listener). As of 5.0.0 the listener resource uses the ORACLE_HOME of the entry:

Table 2. Before and as of 5.0.0
Entry in listener_installed Before 5.0.0 As of 5.0.0

home: <db_homes_config key>

listener.ora in the ORACLE_HOME of home, but a new listener resource was added in the GI home (-oraclehome %CRS_HOME%)

listener.ora and the listener resource (srvctl …​ -oraclehome) in the ORACLE_HOME of home

use_gi_home: true

GI home from oracle_home_gi

GI home from crs_home in /etc/oracle/olr.loc (there is only one Grid Infrastructure / Oracle Restart per host)

Changes in detail:

  • A listener with home is registered with the ORACLE_HOME of home. An existing listener resource in the GI home is modified with srvctl modify listener -oraclehome <ORACLE_HOME of home>. A running listener is stopped before and started after the change, i.e. it runs from the new ORACLE_HOME.

  • A listener with use_gi_home: true stays in the GI / Oracle Restart home.

Who is affected:

  • Inventories with Grid Infrastructure / Oracle Restart and home in listener_installed, where the listener runs from the GI home, e.g. LISTENER with home of the database.

Required actions:

  1. Use use_gi_home: true without home for a listener, which must stay in the GI / Oracle Restart home.

  2. Check the ORACLE_HOME of the listener resources before the upgrade. oradb_manage_db restarts a moved listener, run it in a maintenance window:

    srvctl config listener -listener <listener_name>
Example
listener_installed:
  # listener in the GI / Oracle Restart home (crs_home from /etc/oracle/olr.loc)
  - listener_name: LISTENER
    use_gi_home: true
    state: present
  # additional listener in the ORACLE_HOME of the database, registered with srvctl in this home
  - listener_name: LISTENER2
    home: db19-gi-ee
    state: present

1.21. local_listener in init_parameters of Single Instance databases

As of 5.0.0 the assert of oracle_databases in orasw_meta requires local_listener in init_parameters for every Single Instance database (with and without Oracle Restart) with state: present. RAC and RAC One Node databases are not checked, Clusterware sets local_listener.

Why:

DBCA sets local_listener to an alias, e.g. LISTENER_<DB_NAME>, and writes the alias into tnsnames.ora of the ORACLE_HOME (with Read-Only Oracle Homes in $ORACLE_BASE/homes/<oracle_home_name>/network/admin). After a switch of the ORACLE_HOME (Out-of-Place Patching, see out_of_place_patching.adoc) the alias is missing in tnsnames.ora of the new ORACLE_HOME. The instance cannot resolve local_listener and does not register its services at the listener (ORA-12514 for clients). An EZConnect address in local_listener needs no entry in tnsnames.ora.

Who is affected:

  • Inventories with a Single Instance database in oracle_databases without local_listener in init_parameters. The playbooks fail in the assert of orasw_meta:

    local_listener is missing in init_parameters of <oracle_db_name>, ...

Required actions:

  1. Add local_listener with EZConnect (//<host>:<port>) to init_parameters of the database. localhost and the port of the listener avoid an extra entry in tnsnames.ora.

  2. Add one address per listener, if the instance must register at more than one listener, e.g. '(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=localhost)(PORT=1521))(ADDRESS=(PROTOCOL=TCP)(HOST=localhost)(PORT=1523)))'.

  3. Existing databases: oradb_manage_parameters changes local_listener with scope: both, the instance registers at the listener without restart. The entries of DBCA in tnsnames.ora are not removed by ansible-oracle.

Note
localhost requires a listener on the loopback address. A listener with the hostname in HOST listens on all addresses of the host, unless IP=FIRST is set in listener.ora. Use the hostname or the address of the listener otherwise, e.g. //{{ ansible_hostname }}:1521.
Example
oracle_databases:
  - oracle_db_name: DB1
    oracle_db_type: SI
    listener_port: 1521
    init_parameters:
      - {name: local_listener, value: '//localhost:1521', scope: both, state: present}

1.22. oracle_databases: is_container and omf are true by default

As of 5.0.0 the attributes is_container and omf of oracle_databases are true by default. They need not to be defined in oracle_databases anymore.

Why:

26ai supports only Container Databases and ansible-oracle uses Oracle Managed Files for tablespaces by default. The defaults simplify the inventory.

Who is affected:

  • Inventories with a 19c database in oracle_databases without is_container. Before 5.0.0 a non-CDB was created, now a CDB is created. The tasks for PDBs (oradb_manage_pdb), the timezone upgrade (oradb_tzupgrade) and the switch of the ORACLE_HOME treat the database as CDB.

  • Inventories with a database in oracle_databases without omf. Before 5.0.0 dbca was called with -useOMF false, now with -useOMF true. omf is used during the creation of a database with dbca only.

Required actions:

  1. Set is_container: false for a 19c non-CDB.

  2. Use OMF for new databases. OMF is strongly recommended in ansible-oracle.

  3. Without OMF: set omf: false and use an own DBCA template without OMF (dbca_templatename). The DBCA templates of ansible-oracle are made for OMF. Databases without OMF are not tested anymore.

Example
oracle_databases:
  - oracle_db_name: DB1
    home: db19-si-ee
    is_container: false   # non-CDB, 19c only
    # not recommended and not tested:
    # omf: false          # dbca -useOMF false
    # dbca_templatename: <own DBCA template without OMF>

1.23. oracle_databases: db_create_file_dest and db_recovery_file_dest in init_parameters

As of 5.0.0 the assert of oracle_databases in orasw_meta requires db_create_file_dest and db_recovery_file_dest in init_parameters for every database with state: present and omf: true (default).

Why:

The parameters are needed in different situations, e.g. for dbca, standby databases (RMAN duplicate) and the directories of a new database. They are defined directly in init_parameters instead of deriving them from other variables. dbca uses the values for the datafile and recovery area destination. The global defaults oracle_dbf_dir_fs and oracle_reco_dir_fs are only used with omf: false (only storage_type: FS, own DBCA template, not tested).

Who is affected:

  • Inventories with a database in oracle_databases without db_create_file_dest or db_recovery_file_dest in init_parameters. The playbooks fail in the assert of orasw_meta:

    <oracle_db_name>: omf: true (default) needs db_create_file_dest and db_recovery_file_dest in init_parameters, ...

Required actions:

  1. Add db_create_file_dest and db_recovery_file_dest to init_parameters. Use the values of datafile_dest and recoveryfile_dest, if they were defined.

  2. Existing databases: use the current values of the database (show parameter db_create_file_dest, show parameter db_recovery_file_dest), otherwise oradb_manage_parameters changes them.

  3. Define db_recovery_file_dest_size before db_recovery_file_dest in init_parameters for existing databases without a recovery area (ORA-19802).

Example
oracle_databases:
  - oracle_db_name: DB1
    init_parameters:
      - {name: db_create_file_dest, value: '/u02/oradata', scope: both, state: present}
      - {name: db_recovery_file_dest_size, value: '10G', scope: both, state: present, dbca: false}
      - {name: db_recovery_file_dest, value: '/u02/fra', scope: both, state: present}

1.24. oracle_databases: datafile_dest and recoveryfile_dest are removed

As of 5.0.0 the attributes datafile_dest and recoveryfile_dest of oracle_databases are removed. They are redundant to db_create_file_dest and db_recovery_file_dest in init_parameters. datafile_dest in oracle_pdbs is not affected.

Who is affected:

  • Inventories with datafile_dest or recoveryfile_dest in oracle_databases. The playbooks fail in the assert of orasw_meta:

    <oracle_db_name>: datafile_dest and recoveryfile_dest in oracle_databases are removed. ...

Required actions:

  1. Move the values to db_create_file_dest and db_recovery_file_dest in init_parameters.

  2. Remove datafile_dest and recoveryfile_dest from oracle_databases.

  3. Databases with omf: false: the destinations are oracle_dbf_dir_fs and oracle_reco_dir_fs (global per host).

Before
oracle_databases:
  - oracle_db_name: DB1
    is_container: true
    datafile_dest: /u02/oradata
    recoveryfile_dest: /u02/fra
    init_parameters:
      - {name: db_create_file_dest, value: '/u02/oradata', scope: both, state: present}
After
oracle_databases:
  - oracle_db_name: DB1
    init_parameters:
      - {name: db_create_file_dest, value: '/u02/oradata', scope: both, state: present}
      - {name: db_recovery_file_dest, value: '/u02/fra', scope: both, state: present}

1.25. oracle_databases: omf false not allowed with ASM, oracle_dbf_dir_asm and oracle_reco_dir_asm removed

As of 5.0.0 the assert of oracle_databases in orasw_meta fails for a database with storage_type: ASM and omf: false. ASM without OMF makes no sense in practice. The variables oracle_dbf_dir_asm and oracle_reco_dir_asm are removed, the disk groups are taken from db_create_file_dest and db_recovery_file_dest in init_parameters.

oradb_rman: the templates parameter_rac and parameter_fra_disk use db_create_file_dest from init_parameters for the snapshot controlfile instead of oracle_dbf_dir_asm. Before, parameter_fra_disk created a wrong name with two ` (`+DATA).

Who is affected:

  • Inventories with a database with storage_type: ASM and omf: false. The playbooks fail in the assert of orasw_meta:

    <oracle_db_name>: omf: false is not allowed with storage_type: ASM. ...
  • Inventories with oracle_dbf_dir_asm or oracle_reco_dir_asm. The variables have no effect anymore.

Required actions:

  1. Remove omf: false from ASM databases and add db_create_file_dest and db_recovery_file_dest to init_parameters.

  2. Remove oracle_dbf_dir_asm and oracle_reco_dir_asm from the inventory.

Example
oracle_databases:
  - oracle_db_name: DB1
    storage_type: ASM
    init_parameters:
      - {name: db_create_file_dest, value: '+DATA', scope: both, state: present}
      - {name: db_recovery_file_dest_size, value: '10G', scope: both, state: present, dbca: false}
      - {name: db_recovery_file_dest, value: '+FRA', scope: both, state: present}

1.26. oracle_databases: max_pdbs in init_parameters of Container Databases

As of 5.0.0 the assert of oracle_databases in orasw_meta fails for a Container Database (is_container: true, default as of 5.0.0) with state: present without max_pdbs in init_parameters (without sid or sid: '*'). max_pdbs defines explicitly how many PDBs are allowed by the license. The value must be an integer:

Edition (db_homes_config) Maximum max_pdbs Remark

SE2 (SE)

3

EE

1024

More than 3 PDBs require a license for the Multitenant Option!

Important
Enterprise Edition without a license for the Multitenant Option allows only 3 PDBs, like Standard Edition 2. ansible-oracle has no switch for licensed options yet, so the assert allows up to 1024 PDBs for EE. Check your license before you set max_pdbs greater than 3.

Who is affected:

  • Inventories with a Container Database without max_pdbs in init_parameters, or with a value greater than 3 (SE2) or 1024 (EE). This includes 19c databases without is_container, which are Container Databases as of 5.0.0. The playbooks fail in the assert of orasw_meta:

    <oracle_db_name>: is_container: true (default) needs max_pdbs in init_parameters with an integer value <= <limit> for edition <edition> ...

Required actions:

  1. Add max_pdbs with the number of PDBs allowed by your license to init_parameters. max_pdbs is set by dbca for a new database and changed by oradb_manage_parameters for an existing database.

Example
oracle_databases:
  - oracle_db_name: DB1
    init_parameters:
      - {name: max_pdbs, value: '3', scope: both, state: present}

1.27. oracle_databases: control_management_pack_access in init_parameters of Enterprise Edition databases

As of 5.0.0 the assert of oracle_databases in orasw_meta fails for a database of an Enterprise Edition home (edition: EE in db_homes_config) with state: present without control_management_pack_access in init_parameters (without sid or sid: '*'). control_management_pack_access defines explicitly which Management Packs are licensed. Without the parameter, the Oracle default for Enterprise Edition is DIAGNOSTIC+TUNING, which needs a license for the Diagnostics and Tuning Pack.

Value License

NONE

no Management Pack

DIAGNOSTIC

Diagnostics Pack

DIAGNOSTIC+TUNING

Diagnostics Pack and Tuning Pack

The parameter is optional for Standard Edition 2. If it is defined, the value must be NONE, the Management Packs are not available for Standard Edition 2.

Important
Set the value according to your license. The Management Packs are options of the Enterprise Edition. ansible-oracle has no switches for licensed options yet. Check if further settings are needed for your licensed options.

Who is affected:

  • Inventories with a database of an Enterprise Edition home without control_management_pack_access in init_parameters, or with another value than NONE, DIAGNOSTIC or DIAGNOSTIC+TUNING.

  • Inventories with a database of a Standard Edition 2 home with control_management_pack_access other than NONE. The playbooks fail in the assert of orasw_meta:

    <oracle_db_name>: control_management_pack_access in init_parameters must be one of NONE, DIAGNOSTIC or DIAGNOSTIC+TUNING and is mandatory for Enterprise Edition ...

Required actions:

  1. Add control_management_pack_access with the value allowed by your license to init_parameters. For an existing database, oradb_manage_parameters changes the parameter to the value from the inventory.

Example
oracle_databases:
  - oracle_db_name: DB1
    init_parameters:
      - {name: control_management_pack_access, value: 'NONE', scope: both, state: present}

1.28. oracle_databases: sga_target and pga_aggregate_target in init_parameters

As of 5.0.0 the assert of oracle_databases in orasw_meta fails for a database with state: present without sga_target or pga_aggregate_target in init_parameters. These are the essential memory parameters of an Oracle database and must be defined explicitly. Entries with sid are accepted (instance specific values for RAC).

oracle_db_mem_totalmb (totalMemory in dbca) is not supported anymore, the assert fails if it is set. Before, the assert required either oracle_db_mem_totalmb or sga_target in init_parameters.

Who is affected:

  • Inventories with a database without sga_target or pga_aggregate_target in init_parameters, or with oracle_db_mem_totalmb. The playbooks fail in the assert of orasw_meta:

    <oracle_db_name>: sga_target and pga_aggregate_target are essential memory parameters and must be defined in init_parameters ...

Required actions:

  1. Add sga_target and pga_aggregate_target to init_parameters.

  2. Remove oracle_db_mem_totalmb.

Example
oracle_databases:
  - oracle_db_name: DB1
    init_parameters:
      - {name: sga_target, value: '2G', scope: spfile, state: present}
      - {name: pga_aggregate_target, value: '512M', scope: both, state: present}

1.29. oracle_databases: no memory_target and memory_max_target with Hugepages

As of 5.0.0 the assert of oracle_databases in orasw_meta fails for a database with state: present with memory_target or memory_max_target in init_parameters (also with sid) if Hugepages are configured (configure_hugepages: true, default of orahost). Automatic Memory Management (AMM) prevents the usage of Hugepages. Entries with state: absent are allowed to remove the parameters from the spfile.

Who is affected:

  • Inventories with a database with memory_target or memory_max_target in init_parameters and without configure_hugepages: false. The playbooks fail in the assert of orasw_meta:

    <oracle_db_name>: memory_target and memory_max_target are not allowed in init_parameters with Hugepages ...

Required actions:

  1. Use sga_target and pga_aggregate_target (Automatic Shared Memory Management) instead of AMM.

  2. Set state: absent for memory_target and memory_max_target to remove them from the spfile of existing databases, or set configure_hugepages: false if Hugepages are not used.

Example
oracle_databases:
  - oracle_db_name: DB1
    init_parameters:
      - {name: memory_target, value: '0', scope: spfile, state: absent}
      - {name: memory_max_target, value: '0', scope: spfile, state: absent}
      - {name: sga_target, value: '2G', scope: spfile, state: present}
      - {name: pga_aggregate_target, value: '512M', scope: both, state: present}

1.30. Role oraswahf_install replaced by ahf

The role oraswahf_install was an empty placeholder for the installation of Oracle Autonomous Health Framework (AHF) - it had no tasks and no variables. It is removed and replaced by the new role ahf, which installs, upgrades and configures AHF. The central web interface AHF Fleet Insights is installed with the new role ahf_fleet_insights.

Note
AHF is not installed by oraswahf_install, existing installations are not affected. Only playbooks, which reference the role, fail with the role 'oraswahf_install' was not found.
Before: own playbook
- hosts: dbfs
  become: true
  roles:
    - opitzconsulting.ansible_oracle.oraswahf_install
After: own playbook or playbooks/ahf.yml
- hosts: dbfs
  become: true
  roles:
    - opitzconsulting.ansible_oracle.ahf

The variables and the decisions for an installation are described in Oracle Autonomous Health Framework (AHF).

1.31. oracle_databases: processes in init_parameters

As of 5.0.0 the assert of oracle_databases in orahost_meta fails for a database with state: present without processes in init_parameters, or with a value which is not an integer > 0. Entries with sid are accepted (instance specific values for RAC).

processes is needed to calculate kernel.sem in orahost_meta and by further asserts. Before, a database without processes failed with an undefined variable (oracle_databases_processes_max), or kernel.sem was calculated without the databases lacking processes.

Note
In practice the breaking change is usually irrelevant: the default of processes is too small in most cases anyway and should be set explicitly.

The assert is in orahost_meta, because orahost_meta runs before the asserts of orasw_meta and the role orahost uses only orahost_meta. It is disabled together with the other asserts of oracle_databases by orasw_meta_assert_oracle_databases: false.

Who is affected:

  • Inventories with a database without processes in init_parameters. The playbooks fail in the assert of orahost_meta:

    <oracle_db_name>: processes must be defined in init_parameters with an integer value > 0 ...

Required actions:

  1. Add processes to init_parameters. For an existing database, use the current value (show parameter processes) to avoid a change of the spfile and a restart.

Example
oracle_databases:
  - oracle_db_name: DB1
    init_parameters:
      - {name: processes, value: '640', scope: spfile, state: present}

1.32. Default of oracle_install_version_gi is 26ai

As of 5.0.0 the default of oracle_install_version_gi is 26.1.0.0 (26ai) instead of 19.3.0.0 (19c). New installations should use the current release, an older release as default makes no sense anymore.

Note
In practice the breaking change is usually irrelevant: oracle_install_version_gi must match the installation media of Grid Infrastructure (oracle_sw_image_gi, oracle_install_image_gi) and should be set in every inventory with Grid Infrastructure or Oracle Restart.

oracle_install_version_gi is only used with oracle_install_option_gi: HA_CONFIG or CRS_CONFIG. Inventories without Grid Infrastructure or Oracle Restart are not affected.

Who is affected:

  • Inventories with oracle_install_option_gi: HA_CONFIG or CRS_CONFIG without oracle_install_version_gi. The variable selects the response file, the task file and the installation media of oraswgi_install, and the key in gi_patches.

  • The default of oracle_home_gi contains the version: {{ oracle_base }}/{{ oracle_install_version_gi }}/grid (Oracle Restart) and /u01/app/{{ oracle_install_version_gi }}/grid (Grid Infrastructure). Without oracle_install_version_gi and without oracle_home_gi in inventory, oracle_home_gi changes from …​/19.3.0.0/grid to …​/26.1.0.0/grid.

    Warning
    For an installed Oracle Restart, a different oracle_home_gi starts the switch into a new home (Out-of-Place Patching, switch_home.yml of oraswgi_install). Set oracle_install_version_gi (and oracle_home_gi) before the first run with 5.0.0.

Required actions:

  1. Set oracle_install_version_gi to the base release of the installation media (19c: 19.3.0.0, 26ai: 26.1.0.0).

  2. Recommended: set oracle_home_gi as well, to be independent from the default.

Example: Oracle Restart 19c
oracle_install_option_gi: HA_CONFIG
oracle_install_version_gi: 19.3.0.0
oracle_home_gi: /u01/app/oracle/19.3.0.0/grid   # the former default

2. Adding new breaking changes

Every changelog fragment with a breaking_changes entry needs an entry in this guide:

  1. Add a row to the overview table of the next major version. Create the version section, if it does not exist.

  2. Describe the change in an own subsection: what changed, why, who is affected, before/after and the required action with an example.

  3. Reference this guide in the changelog fragment (see doc/guides/breaking_changes.adoc).