2026-06-28 10:00:23
This commit is contained in:
@@ -0,0 +1,119 @@
|
||||
---
|
||||
# Playbook: ora_stand_datapatch.yml
|
||||
|
||||
# Usage example:
|
||||
|
||||
# ansible-playbook playbooks/ora_stand_datapatch.yml \
|
||||
# -e server=togoria \
|
||||
# -e oracle_sid=NABOOPRD
|
||||
|
||||
|
||||
- name: Gather facts for a specific inventory host
|
||||
hosts: "{{ server }}"
|
||||
gather_facts: yes
|
||||
become: true
|
||||
become_user: oracle
|
||||
become_method: su
|
||||
|
||||
pre_tasks:
|
||||
- name: Ensure 'server' variable is provided
|
||||
assert:
|
||||
that: server is defined
|
||||
fail_msg: "Please provide the server via -e 'server=<server>'"
|
||||
|
||||
- name: Ensure 'oracle_sid' variable is provided
|
||||
assert:
|
||||
that: oracle_sid is defined
|
||||
fail_msg: "Please provide the oracle_sid via -e 'oracle_sid=<oracle_sid>'"
|
||||
|
||||
tasks:
|
||||
- name: Show selected system facts
|
||||
debug:
|
||||
msg:
|
||||
hostname: "{{ (ansible_facts.nodename | default(ansible_facts.hostname)) | default('unknown') }}"
|
||||
os_family: "{{ ansible_facts.os_family | default(ansible_facts.distribution | default('unknown')) }}"
|
||||
operating_system: "{{ ansible_facts.distribution | default('unknown') }} {{ ansible_facts.distribution_version | default('') }}"
|
||||
ip_address: "{{ ansible_default_ipv4.address | default('unknown') }}"
|
||||
hardware_model: "{{ ansible_facts['machine'] | default('unknown') }}"
|
||||
cpu_count: "{{ ansible_facts['processor_vcpus'] | default(ansible_facts['processor_count'] | default('unknown')) }}"
|
||||
ram_gb: "{{ (ansible_facts['memtotal_mb'] / 1024) | int | default('unknown') }}"
|
||||
|
||||
- name: Source oraenv and display OPatch informations
|
||||
shell: |
|
||||
. oraenv <<< {{ oracle_sid }} && $ORACLE_HOME/OPatch/opatch version && echo && echo && $ORACLE_HOME/OPatch/opatch lspatches
|
||||
register: opatch_output
|
||||
when: oracle_sid is defined
|
||||
|
||||
- name: Display OPatch output
|
||||
debug:
|
||||
var: opatch_output.stdout_lines
|
||||
when: oracle_sid is defined
|
||||
|
||||
- name: Check Oracle instance status via sqlplus as SYSDBA
|
||||
shell: |
|
||||
. oraenv <<< {{ oracle_sid }} >/dev/null 2>&1
|
||||
$ORACLE_HOME/bin/sqlplus -s / as sysdba <<'SQL'
|
||||
set heading off feedback off verify off pagesize 0
|
||||
select status from v$instance;
|
||||
exit
|
||||
SQL
|
||||
register: instance_status
|
||||
changed_when: false
|
||||
when: oracle_sid is defined
|
||||
|
||||
- name: Show Oracle instance status
|
||||
debug:
|
||||
msg: "Oracle instance {{ oracle_sid }} status: {{ instance_status.stdout | trim | default('unknown') }}"
|
||||
when: oracle_sid is defined
|
||||
|
||||
- name: Fail if Oracle instance is not OPEN
|
||||
fail:
|
||||
msg: "Oracle instance {{ oracle_sid }} is not OPEN (status: {{ instance_status.stdout | default('unknown') }})"
|
||||
when: oracle_sid is defined and ("OPEN" not in (instance_status.stdout | default('')))
|
||||
|
||||
- name: List PDBs (if multitenant)
|
||||
shell: |
|
||||
. oraenv <<< {{ oracle_sid }} >/dev/null 2>&1
|
||||
$ORACLE_HOME/bin/sqlplus -s / as sysdba <<'SQL'
|
||||
set heading off feedback off verify off pagesize 0
|
||||
select name||':'||open_mode from v$pdbs where name!='PDB$SEED';
|
||||
exit
|
||||
SQL
|
||||
register: pdb_list
|
||||
failed_when: false
|
||||
changed_when: false
|
||||
when: oracle_sid is defined
|
||||
|
||||
- name: Determine if database is multitenant
|
||||
set_fact:
|
||||
is_multitenant: "{{ (pdb_list.stdout is defined) and ('ORA-' not in pdb_list.stdout) and (pdb_list.stdout | trim != '') }}"
|
||||
when: oracle_sid is defined
|
||||
|
||||
- name: Show PDB list (if multitenant)
|
||||
debug:
|
||||
var: pdb_list.stdout_lines
|
||||
when: oracle_sid is defined and is_multitenant
|
||||
|
||||
- name: Check for non-OPEN PDBs
|
||||
shell: |
|
||||
. oraenv <<< {{ oracle_sid }} >/dev/null 2>&1
|
||||
$ORACLE_HOME/bin/sqlplus -s / as sysdba <<'SQL'
|
||||
set heading off feedback off verify off pagesize 0
|
||||
select name||':'||open_mode from v$pdbs where name!='PDB$SEED' and upper(open_mode) not like '%READ WRITE%';
|
||||
exit
|
||||
SQL
|
||||
register: pdb_not_open
|
||||
failed_when: false
|
||||
changed_when: false
|
||||
when: oracle_sid is defined and is_multitenant
|
||||
|
||||
- name: Filter non-empty PDB results
|
||||
set_fact:
|
||||
pdb_not_open_filtered: "{{ pdb_not_open.stdout_lines | select('match', '^.+:.+$') | list }}"
|
||||
when: oracle_sid is defined and is_multitenant
|
||||
|
||||
- name: Fail if any PDB is not OPEN
|
||||
fail:
|
||||
msg: "PDB(s) not OPEN: {{ pdb_not_open_filtered }}"
|
||||
when: oracle_sid is defined and is_multitenant and (pdb_not_open_filtered | length) > 0
|
||||
|
||||
@@ -0,0 +1,257 @@
|
||||
---
|
||||
# Playbook: ora_stand_patch_oh.yml
|
||||
# Usage example:
|
||||
|
||||
# ansible-playbook playbooks/ora_stand_patch_oh.yml \
|
||||
# -e server=togoria \
|
||||
# -e oracle_sid=NABOOPRD \
|
||||
# -e opatch_zip=/mnt/yavin4/kit/Oracle/opatch/p6880880_190000_Linux-x86-64.zip \
|
||||
# -e dbru_zip=/mnt/yavin4/kit/Oracle/Oracle_Database_19/patch/GIRU_19.29/p38298204_190000_Linux-x86-64.zip
|
||||
|
||||
- name: Gather facts for a specific inventory host
|
||||
hosts: "{{ server }}"
|
||||
gather_facts: yes
|
||||
become: true
|
||||
become_user: oracle
|
||||
become_method: su
|
||||
|
||||
pre_tasks:
|
||||
- name: Ensure 'server' variable is provided
|
||||
assert:
|
||||
that: server is defined
|
||||
fail_msg: "Please provide the server via -e 'server=<server>'"
|
||||
|
||||
- name: Ensure 'oracle_sid' variable is provided
|
||||
assert:
|
||||
that: oracle_sid is defined
|
||||
fail_msg: "Please provide the oracle_sid via -e 'oracle_sid=<oracle_sid>'"
|
||||
|
||||
- name: Ensure 'opatch_zip' variable is provided
|
||||
assert:
|
||||
that: opatch_zip is defined
|
||||
fail_msg: "Please provide the opatch_zip via -e 'opatch_zip=<opatch_zip>'"
|
||||
|
||||
- name: Ensure 'dbru_zip' variable is provided
|
||||
assert:
|
||||
that: dbru_zip is defined
|
||||
fail_msg: "Please provide the dbru_zip via -e 'dbru_zip=<dbru_zip>'"
|
||||
|
||||
tasks:
|
||||
- name: Show selected system facts
|
||||
debug:
|
||||
msg:
|
||||
hostname: "{{ (ansible_facts.nodename | default(ansible_facts.hostname)) | default('unknown') }}"
|
||||
os_family: "{{ ansible_facts.os_family | default(ansible_facts.distribution | default('unknown')) }}"
|
||||
operating_system: "{{ ansible_facts.distribution | default('unknown') }} {{ ansible_facts.distribution_version | default('') }}"
|
||||
ip_address: "{{ ansible_default_ipv4.address | default('unknown') }}"
|
||||
hardware_model: "{{ ansible_facts['machine'] | default('unknown') }}"
|
||||
cpu_count: "{{ ansible_facts['processor_vcpus'] | default(ansible_facts['processor_count'] | default('unknown')) }}"
|
||||
ram_gb: "{{ (ansible_facts['memtotal_mb'] / 1024) | int | default('unknown') }}"
|
||||
|
||||
- name: Source oraenv and display OPatch informations
|
||||
shell: |
|
||||
. oraenv <<< {{ oracle_sid }} && $ORACLE_HOME/OPatch/opatch version && echo && echo && $ORACLE_HOME/OPatch/opatch lspatches
|
||||
register: opatch_output
|
||||
when: oracle_sid is defined
|
||||
|
||||
- name: Display OPatch output
|
||||
debug:
|
||||
var: opatch_output.stdout_lines
|
||||
when: oracle_sid is defined
|
||||
|
||||
- name: Check if any oracle processes are using ORACLE_HOME files
|
||||
shell: |
|
||||
. oraenv <<< {{ oracle_sid }} >/dev/null 2>&1
|
||||
lsof +D "$ORACLE_HOME" 2>/dev/null | grep -v COMMAND | awk '{print $1}' | sort -u || true
|
||||
args:
|
||||
executable: /bin/bash
|
||||
register: oracle_processes_using_oh
|
||||
changed_when: false
|
||||
failed_when: false
|
||||
when: oracle_sid is defined
|
||||
|
||||
- name: List oracle processes using ORACLE_HOME files and fail if any found
|
||||
fail:
|
||||
msg: |
|
||||
Found oracle user processes using files from $ORACLE_HOME.
|
||||
Cannot proceed with patching while processes are active:
|
||||
{{ oracle_processes_using_oh.stdout_lines }}
|
||||
when:
|
||||
- oracle_sid is defined
|
||||
- oracle_processes_using_oh.stdout_lines | default([]) | length > 0
|
||||
|
||||
- name: Remove $ORACLE_HOME/OPatch directory
|
||||
shell: |
|
||||
. oraenv <<< {{ oracle_sid }}
|
||||
if [ -d "$ORACLE_HOME/OPatch" ]; then
|
||||
rm -rf "$ORACLE_HOME/OPatch"
|
||||
echo removed
|
||||
else
|
||||
echo not_found
|
||||
fi
|
||||
args:
|
||||
executable: /bin/bash
|
||||
register: remove_opatch
|
||||
changed_when: "'removed' in remove_opatch.stdout"
|
||||
failed_when: false
|
||||
when: oracle_sid is defined
|
||||
|
||||
- name: Show OPatch removal result
|
||||
debug:
|
||||
msg: "OPatch removal: {{ remove_opatch.stdout | default('no_output') }}"
|
||||
when: oracle_sid is defined
|
||||
|
||||
- name: Copy OPatch zip to remote host
|
||||
copy:
|
||||
src: "{{ opatch_zip }}"
|
||||
dest: "/tmp/{{ opatch_zip | basename }}"
|
||||
mode: '0644'
|
||||
when: opatch_zip is defined
|
||||
|
||||
- name: Extract OPatch zip into $ORACLE_HOME
|
||||
shell: |
|
||||
. oraenv <<< {{ oracle_sid }}
|
||||
unzip -o "/tmp/{{ opatch_zip | basename }}" -d "$ORACLE_HOME"
|
||||
args:
|
||||
executable: /bin/bash
|
||||
register: opatch_unzip
|
||||
changed_when: opatch_unzip.rc == 0 and (opatch_unzip.stdout is defined)
|
||||
failed_when: opatch_unzip.rc != 0
|
||||
when: opatch_zip is defined
|
||||
|
||||
- name: Remove uploaded OPatch zip from remote
|
||||
file:
|
||||
path: "/tmp/{{ opatch_zip | basename }}"
|
||||
state: absent
|
||||
when: opatch_zip is defined
|
||||
|
||||
- name: Source oraenv and display OPatch informations
|
||||
shell: |
|
||||
. oraenv <<< {{ oracle_sid }} && $ORACLE_HOME/OPatch/opatch version && echo && echo && $ORACLE_HOME/OPatch/opatch lspatches
|
||||
register: opatch_output
|
||||
when: oracle_sid is defined
|
||||
|
||||
- name: Display OPatch output
|
||||
debug:
|
||||
var: opatch_output.stdout_lines
|
||||
when: oracle_sid is defined
|
||||
|
||||
- name: Remove /app/oracle/staging_area if present
|
||||
file:
|
||||
path: /app/oracle/staging_area
|
||||
state: absent
|
||||
|
||||
- name: Recreate /app/oracle/staging_area
|
||||
file:
|
||||
path: /app/oracle/staging_area
|
||||
state: directory
|
||||
mode: '0755'
|
||||
|
||||
- name: Check local dbru_zip path exists on controller (only if provided)
|
||||
stat:
|
||||
path: "{{ dbru_zip }}"
|
||||
delegate_to: localhost
|
||||
run_once: true
|
||||
register: local_zip_stat
|
||||
when: dbru_zip is defined
|
||||
|
||||
- name: Fail if local dbru_zip file not found on controller
|
||||
fail:
|
||||
msg: "Local zip file {{ dbru_zip }} not found on controller"
|
||||
when: dbru_zip is defined and (local_zip_stat.stat is not defined or not local_zip_stat.stat.exists)
|
||||
run_once: true
|
||||
|
||||
- name: Copy local dbru_zip to remote staging_area
|
||||
copy:
|
||||
src: "{{ dbru_zip }}"
|
||||
dest: "/app/oracle/staging_area/{{ dbru_zip | basename }}"
|
||||
mode: '0644'
|
||||
when: dbru_zip is defined
|
||||
|
||||
- name: Unarchive uploaded zip into staging_area
|
||||
unarchive:
|
||||
src: "/app/oracle/staging_area/{{ dbru_zip | basename }}"
|
||||
dest: /app/oracle/staging_area
|
||||
remote_src: yes
|
||||
when: dbru_zip is defined
|
||||
|
||||
- name: Remove uploaded zip from remote staging_area
|
||||
file:
|
||||
path: "/app/oracle/staging_area/{{ dbru_zip | basename }}"
|
||||
state: absent
|
||||
when: dbru_zip is defined
|
||||
|
||||
- name: Find extracted directories under staging_area
|
||||
find:
|
||||
paths: /app/oracle/staging_area
|
||||
file_type: directory
|
||||
depth: 1
|
||||
register: staging_dirs
|
||||
when: dbru_zip is defined
|
||||
|
||||
- name: Show staging directories found
|
||||
debug:
|
||||
var: staging_dirs.files
|
||||
when: dbru_zip is defined
|
||||
|
||||
- name: Find all subdirectories inside extracted main dirs (depth=2)
|
||||
shell: |
|
||||
find /app/oracle/staging_area -mindepth 2 -maxdepth 2 -type d -not -name automation -print
|
||||
args:
|
||||
executable: /bin/bash
|
||||
register: all_subdirs
|
||||
changed_when: false
|
||||
when: dbru_zip is defined
|
||||
|
||||
- name: Show all subdirectories to process
|
||||
debug:
|
||||
var: all_subdirs.stdout_lines
|
||||
when: dbru_zip is defined and all_subdirs is defined
|
||||
|
||||
- name: Apply OPatch for each extracted subdirectory (clean chdir)
|
||||
shell: |
|
||||
. oraenv <<< {{ oracle_sid }}
|
||||
export PATH=$PATH:$ORACLE_HOME/OPatch
|
||||
if [ -x "$ORACLE_HOME/OPatch/opatch" ]; then
|
||||
$ORACLE_HOME/OPatch/opatch apply -silent
|
||||
else
|
||||
echo "opatch_not_found"
|
||||
exit 2
|
||||
fi
|
||||
args:
|
||||
executable: /bin/bash
|
||||
chdir: "{{ item }}"
|
||||
loop: "{{ all_subdirs.stdout_lines | default([]) }}"
|
||||
loop_control:
|
||||
label: "{{ item }}"
|
||||
register: opatch_apply_results
|
||||
failed_when: false
|
||||
changed_when: false
|
||||
when: dbru_zip is defined and all_subdirs is defined and (all_subdirs.stdout_lines | length) > 0
|
||||
|
||||
- name: Show OPatch apply results (stdout lines)
|
||||
debug:
|
||||
var: opatch_apply_results.results | map(attribute='stdout_lines') | list
|
||||
when: dbru_zip is defined and opatch_apply_results is defined
|
||||
|
||||
- name: Collect failed OPatch applies
|
||||
set_fact:
|
||||
failed_applies: "{{ opatch_apply_results.results | selectattr('rc','ne',0) | map(attribute='item') | list }}"
|
||||
when: dbru_zip is defined and opatch_apply_results is defined
|
||||
|
||||
- name: Fail if any OPatch apply failed
|
||||
fail:
|
||||
msg: "OPatch apply failed in: {{ failed_applies }}"
|
||||
when: dbru_zip is defined and failed_applies is defined and (failed_applies | length) > 0
|
||||
|
||||
- name: Remove /app/oracle/staging_area if present
|
||||
file:
|
||||
path: /app/oracle/staging_area
|
||||
state: absent
|
||||
|
||||
- name: Recreate /app/oracle/staging_area
|
||||
file:
|
||||
path: /app/oracle/staging_area
|
||||
state: directory
|
||||
mode: '0755'
|
||||
|
||||
@@ -1,99 +0,0 @@
|
||||
---
|
||||
# Playbook: ora_standalone_patch.yml
|
||||
# Usage: ansible-playbook playbooks/ora_standalone_patch.yml -e "server=togoria oracle_sid=NABOOPRD opatch_zip=/mnt/yavin4/kit/Oracle/opatch/p6880880_190000_Linux-x86-64.zip dbru_zip=/mnt/yavin4/kit/Oracle/Oracle_Database_19/patch/GIRU_19.29/p38298204_190000_Linux-x86-64.zip"
|
||||
|
||||
- name: Gather facts for a specific inventory host
|
||||
hosts: "{{ server }}"
|
||||
gather_facts: yes
|
||||
become: true
|
||||
become_user: oracle
|
||||
become_method: su
|
||||
|
||||
pre_tasks:
|
||||
- name: Ensure 'server' variable is provided
|
||||
assert:
|
||||
that: server is defined
|
||||
fail_msg: "Please provide the server via -e 'server=<server>'"
|
||||
|
||||
- name: Ensure 'oracle_sid' variable is provided
|
||||
assert:
|
||||
that: oracle_sid is defined
|
||||
fail_msg: "Please provide the oracle_sid via -e 'oracle_sid=<oracle_sid>'"
|
||||
|
||||
- name: Ensure 'opatch_zip' variable is provided
|
||||
assert:
|
||||
that: opatch_zip is defined
|
||||
fail_msg: "Please provide the opatch_zip via -e 'opatch_zip=<opatch_zip>'"
|
||||
|
||||
- name: Ensure 'dbru_zip' variable is provided
|
||||
assert:
|
||||
that: dbru_zip is defined
|
||||
fail_msg: "Please provide the dbru_zip via -e 'dbru_zip=<dbru_zip>'"
|
||||
|
||||
tasks:
|
||||
- name: Show selected system facts
|
||||
debug:
|
||||
msg:
|
||||
hostname: "{{ (ansible_facts.nodename | default(ansible_facts.hostname)) | default('unknown') }}"
|
||||
os_family: "{{ ansible_facts.os_family | default(ansible_facts.distribution | default('unknown')) }}"
|
||||
operating_system: "{{ ansible_facts.distribution | default('unknown') }} {{ ansible_facts.distribution_version | default('') }}"
|
||||
ip_address: "{{ ansible_default_ipv4.address | default('unknown') }}"
|
||||
hardware_model: "{{ ansible_facts['machine'] | default('unknown') }}"
|
||||
cpu_count: "{{ ansible_facts['processor_vcpus'] | default(ansible_facts['processor_count'] | default('unknown')) }}"
|
||||
ram_gb: "{{ (ansible_facts['memtotal_mb'] / 1024) | int | default('unknown') }}"
|
||||
|
||||
- name: Source oraenv and display OPatch informations
|
||||
shell: |
|
||||
. oraenv <<< {{ oracle_sid }} && $ORACLE_HOME/OPatch/opatch version && echo && echo && $ORACLE_HOME/OPatch/opatch lspatches
|
||||
register: opatch_output
|
||||
when: oracle_sid is defined
|
||||
|
||||
- name: Display OPatch directory contents
|
||||
debug:
|
||||
var: opatch_output.stdout_lines
|
||||
when: oracle_sid is defined
|
||||
|
||||
# - name: Remove /app/oracle/staging_area if present
|
||||
# file:
|
||||
# path: /app/oracle/staging_area
|
||||
# state: absent
|
||||
|
||||
# - name: Recreate /app/oracle/staging_area
|
||||
# file:
|
||||
# path: /app/oracle/staging_area
|
||||
# state: directory
|
||||
# mode: '0755'
|
||||
|
||||
# - name: Check local zip path exists on controller (only if provided)
|
||||
# stat:
|
||||
# path: "{{ dbru_zip }}"
|
||||
# delegate_to: localhost
|
||||
# run_once: true
|
||||
# register: local_zip_stat
|
||||
# when: dbru_zip is defined
|
||||
|
||||
# - name: Fail if local zip file not found on controller
|
||||
# fail:
|
||||
# msg: "Local zip file {{ dbru_zip }} not found on controller"
|
||||
# when: dbru_zip is defined and (local_zip_stat.stat is not defined or not local_zip_stat.stat.exists)
|
||||
# run_once: true
|
||||
|
||||
# - name: Copy local zip file to remote staging_area
|
||||
# copy:
|
||||
# src: "{{ dbru_zip }}"
|
||||
# dest: "/app/oracle/staging_area/{{ dbru_zip | basename }}"
|
||||
# mode: '0644'
|
||||
# when: dbru_zip is defined
|
||||
|
||||
# - name: Unarchive uploaded zip into staging_area
|
||||
# unarchive:
|
||||
# src: "/app/oracle/staging_area/{{ dbru_zip | basename }}"
|
||||
# dest: /app/oracle/staging_area
|
||||
# remote_src: yes
|
||||
# when: dbru_zip is defined
|
||||
|
||||
# - name: Remove uploaded zip from remote staging_area
|
||||
# file:
|
||||
# path: "/app/oracle/staging_area/{{ dbru_zip | basename }}"
|
||||
# state: absent
|
||||
# when: dbru_zip is defined
|
||||
@@ -0,0 +1,289 @@
|
||||
---
|
||||
# Playbook: ora_standalone_patch.yml
|
||||
# Usage: ansible-playbook playbooks/ora_standalone_patch.yml -e "server=togoria oracle_sid=NABOOPRD opatch_zip=/mnt/yavin4/kit/Oracle/opatch/p6880880_190000_Linux-x86-64.zip dbru_zip=/mnt/yavin4/kit/Oracle/Oracle_Database_19/patch/GIRU_19.29/p38298204_190000_Linux-x86-64.zip"
|
||||
|
||||
- name: Gather facts for a specific inventory host
|
||||
hosts: "{{ server }}"
|
||||
gather_facts: yes
|
||||
become: true
|
||||
become_user: oracle
|
||||
become_method: su
|
||||
|
||||
pre_tasks:
|
||||
- name: Ensure 'server' variable is provided
|
||||
assert:
|
||||
that: server is defined
|
||||
fail_msg: "Please provide the server via -e 'server=<server>'"
|
||||
|
||||
- name: Ensure 'oracle_sid' variable is provided
|
||||
assert:
|
||||
that: oracle_sid is defined
|
||||
fail_msg: "Please provide the oracle_sid via -e 'oracle_sid=<oracle_sid>'"
|
||||
|
||||
- name: Ensure 'opatch_zip' variable is provided
|
||||
assert:
|
||||
that: opatch_zip is defined
|
||||
fail_msg: "Please provide the opatch_zip via -e 'opatch_zip=<opatch_zip>'"
|
||||
|
||||
- name: Ensure 'dbru_zip' variable is provided
|
||||
assert:
|
||||
that: dbru_zip is defined
|
||||
fail_msg: "Please provide the dbru_zip via -e 'dbru_zip=<dbru_zip>'"
|
||||
|
||||
tasks:
|
||||
- name: Show selected system facts
|
||||
debug:
|
||||
msg:
|
||||
hostname: "{{ (ansible_facts.nodename | default(ansible_facts.hostname)) | default('unknown') }}"
|
||||
os_family: "{{ ansible_facts.os_family | default(ansible_facts.distribution | default('unknown')) }}"
|
||||
operating_system: "{{ ansible_facts.distribution | default('unknown') }} {{ ansible_facts.distribution_version | default('') }}"
|
||||
ip_address: "{{ ansible_default_ipv4.address | default('unknown') }}"
|
||||
hardware_model: "{{ ansible_facts['machine'] | default('unknown') }}"
|
||||
cpu_count: "{{ ansible_facts['processor_vcpus'] | default(ansible_facts['processor_count'] | default('unknown')) }}"
|
||||
ram_gb: "{{ (ansible_facts['memtotal_mb'] / 1024) | int | default('unknown') }}"
|
||||
|
||||
- name: Source oraenv and display OPatch informations
|
||||
shell: |
|
||||
. oraenv <<< {{ oracle_sid }} && $ORACLE_HOME/OPatch/opatch version && echo && echo && $ORACLE_HOME/OPatch/opatch lspatches
|
||||
register: opatch_output
|
||||
when: oracle_sid is defined
|
||||
|
||||
- name: Display OPatch output
|
||||
debug:
|
||||
var: opatch_output.stdout_lines
|
||||
when: oracle_sid is defined
|
||||
|
||||
- name: Check Oracle instance status via sqlplus as SYSDBA
|
||||
shell: |
|
||||
. oraenv <<< {{ oracle_sid }} >/dev/null 2>&1
|
||||
$ORACLE_HOME/bin/sqlplus -s / as sysdba <<'SQL'
|
||||
set heading off feedback off verify off pagesize 0
|
||||
select status from v$instance;
|
||||
exit
|
||||
SQL
|
||||
register: instance_status
|
||||
changed_when: false
|
||||
when: oracle_sid is defined
|
||||
|
||||
- name: Show Oracle instance status
|
||||
debug:
|
||||
msg: "Oracle instance {{ oracle_sid }} status: {{ instance_status.stdout | trim | default('unknown') }}"
|
||||
when: oracle_sid is defined
|
||||
|
||||
- name: Fail if Oracle instance is not OPEN
|
||||
fail:
|
||||
msg: "Oracle instance {{ oracle_sid }} is not OPEN (status: {{ instance_status.stdout | default('unknown') }})"
|
||||
when: oracle_sid is defined and ("OPEN" not in (instance_status.stdout | default('')))
|
||||
|
||||
- name: List PDBs (if multitenant)
|
||||
shell: |
|
||||
. oraenv <<< {{ oracle_sid }} >/dev/null 2>&1
|
||||
$ORACLE_HOME/bin/sqlplus -s / as sysdba <<'SQL'
|
||||
set heading off feedback off verify off pagesize 0
|
||||
select name||':'||open_mode from v$pdbs where name!='PDB$SEED';
|
||||
exit
|
||||
SQL
|
||||
register: pdb_list
|
||||
failed_when: false
|
||||
changed_when: false
|
||||
when: oracle_sid is defined
|
||||
|
||||
- name: Determine if database is multitenant
|
||||
set_fact:
|
||||
is_multitenant: "{{ (pdb_list.stdout is defined) and ('ORA-' not in pdb_list.stdout) and (pdb_list.stdout | trim != '') }}"
|
||||
when: oracle_sid is defined
|
||||
|
||||
- name: Show PDB list (if multitenant)
|
||||
debug:
|
||||
var: pdb_list.stdout_lines
|
||||
when: oracle_sid is defined and is_multitenant
|
||||
|
||||
- name: Check for non-OPEN PDBs
|
||||
shell: |
|
||||
. oraenv <<< {{ oracle_sid }} >/dev/null 2>&1
|
||||
$ORACLE_HOME/bin/sqlplus -s / as sysdba <<'SQL'
|
||||
set heading off feedback off verify off pagesize 0
|
||||
select name||':'||open_mode from v$pdbs where name!='PDB$SEED' and upper(open_mode) not like '%READ WRITE%';
|
||||
exit
|
||||
SQL
|
||||
register: pdb_not_open
|
||||
failed_when: false
|
||||
changed_when: false
|
||||
when: oracle_sid is defined and is_multitenant
|
||||
|
||||
- name: Filter non-empty PDB results
|
||||
set_fact:
|
||||
pdb_not_open_filtered: "{{ pdb_not_open.stdout_lines | select('match', '^.+:.+$') | list }}"
|
||||
when: oracle_sid is defined and is_multitenant
|
||||
|
||||
- name: Fail if any PDB is not OPEN
|
||||
fail:
|
||||
msg: "PDB(s) not OPEN: {{ pdb_not_open_filtered }}"
|
||||
when: oracle_sid is defined and is_multitenant and (pdb_not_open_filtered | length) > 0
|
||||
|
||||
- name: Remove $ORACLE_HOME/OPatch directory
|
||||
shell: |
|
||||
. oraenv <<< {{ oracle_sid }}
|
||||
if [ -d "$ORACLE_HOME/OPatch" ]; then
|
||||
rm -rf "$ORACLE_HOME/OPatch"
|
||||
echo removed
|
||||
else
|
||||
echo not_found
|
||||
fi
|
||||
args:
|
||||
executable: /bin/bash
|
||||
register: remove_opatch
|
||||
changed_when: "'removed' in remove_opatch.stdout"
|
||||
failed_when: false
|
||||
when: oracle_sid is defined
|
||||
|
||||
- name: Show OPatch removal result
|
||||
debug:
|
||||
msg: "OPatch removal: {{ remove_opatch.stdout | default('no_output') }}"
|
||||
when: oracle_sid is defined
|
||||
|
||||
- name: Copy OPatch zip to remote host
|
||||
copy:
|
||||
src: "{{ opatch_zip }}"
|
||||
dest: "/tmp/{{ opatch_zip | basename }}"
|
||||
mode: '0644'
|
||||
when: opatch_zip is defined
|
||||
|
||||
- name: Extract OPatch zip into $ORACLE_HOME
|
||||
shell: |
|
||||
. oraenv <<< {{ oracle_sid }}
|
||||
unzip -o "/tmp/{{ opatch_zip | basename }}" -d "$ORACLE_HOME"
|
||||
args:
|
||||
executable: /bin/bash
|
||||
register: opatch_unzip
|
||||
changed_when: opatch_unzip.rc == 0 and (opatch_unzip.stdout is defined)
|
||||
failed_when: opatch_unzip.rc != 0
|
||||
when: opatch_zip is defined
|
||||
|
||||
- name: Remove uploaded OPatch zip from remote
|
||||
file:
|
||||
path: "/tmp/{{ opatch_zip | basename }}"
|
||||
state: absent
|
||||
when: opatch_zip is defined
|
||||
|
||||
- name: Source oraenv and display OPatch informations
|
||||
shell: |
|
||||
. oraenv <<< {{ oracle_sid }} && $ORACLE_HOME/OPatch/opatch version && echo && echo && $ORACLE_HOME/OPatch/opatch lspatches
|
||||
register: opatch_output
|
||||
when: oracle_sid is defined
|
||||
|
||||
- name: Display OPatch output
|
||||
debug:
|
||||
var: opatch_output.stdout_lines
|
||||
when: oracle_sid is defined
|
||||
|
||||
- name: Remove /app/oracle/staging_area if present
|
||||
file:
|
||||
path: /app/oracle/staging_area
|
||||
state: absent
|
||||
|
||||
- name: Recreate /app/oracle/staging_area
|
||||
file:
|
||||
path: /app/oracle/staging_area
|
||||
state: directory
|
||||
mode: '0755'
|
||||
|
||||
- name: Check local dbru_zip path exists on controller (only if provided)
|
||||
stat:
|
||||
path: "{{ dbru_zip }}"
|
||||
delegate_to: localhost
|
||||
run_once: true
|
||||
register: local_zip_stat
|
||||
when: dbru_zip is defined
|
||||
|
||||
- name: Fail if local dbru_zip file not found on controller
|
||||
fail:
|
||||
msg: "Local zip file {{ dbru_zip }} not found on controller"
|
||||
when: dbru_zip is defined and (local_zip_stat.stat is not defined or not local_zip_stat.stat.exists)
|
||||
run_once: true
|
||||
|
||||
- name: Copy local dbru_zip to remote staging_area
|
||||
copy:
|
||||
src: "{{ dbru_zip }}"
|
||||
dest: "/app/oracle/staging_area/{{ dbru_zip | basename }}"
|
||||
mode: '0644'
|
||||
when: dbru_zip is defined
|
||||
|
||||
- name: Unarchive uploaded zip into staging_area
|
||||
unarchive:
|
||||
src: "/app/oracle/staging_area/{{ dbru_zip | basename }}"
|
||||
dest: /app/oracle/staging_area
|
||||
remote_src: yes
|
||||
when: dbru_zip is defined
|
||||
|
||||
- name: Remove uploaded zip from remote staging_area
|
||||
file:
|
||||
path: "/app/oracle/staging_area/{{ dbru_zip | basename }}"
|
||||
state: absent
|
||||
when: dbru_zip is defined
|
||||
|
||||
- name: Find extracted directories under staging_area
|
||||
find:
|
||||
paths: /app/oracle/staging_area
|
||||
file_type: directory
|
||||
depth: 1
|
||||
register: staging_dirs
|
||||
when: dbru_zip is defined
|
||||
|
||||
- name: Show staging directories found
|
||||
debug:
|
||||
var: staging_dirs.files
|
||||
when: dbru_zip is defined
|
||||
|
||||
- name: Find all subdirectories inside extracted main dirs (depth=2)
|
||||
shell: |
|
||||
find /app/oracle/staging_area -mindepth 2 -maxdepth 2 -type d -print
|
||||
args:
|
||||
executable: /bin/bash
|
||||
register: all_subdirs
|
||||
changed_when: false
|
||||
when: dbru_zip is defined
|
||||
|
||||
- name: Show all subdirectories to process
|
||||
debug:
|
||||
var: all_subdirs.stdout_lines
|
||||
when: dbru_zip is defined and all_subdirs is defined
|
||||
|
||||
- name: Apply OPatch for each extracted subdirectory (clean chdir)
|
||||
shell: |
|
||||
. oraenv <<< {{ oracle_sid }}
|
||||
export PATH=$PATH:$ORACLE_HOME/OPatch
|
||||
if [ -x "$ORACLE_HOME/OPatch/opatch" ]; then
|
||||
$ORACLE_HOME/OPatch/opatch apply -silent
|
||||
else
|
||||
echo "opatch_not_found"
|
||||
exit 2
|
||||
fi
|
||||
args:
|
||||
executable: /bin/bash
|
||||
chdir: "{{ item }}"
|
||||
loop: "{{ all_subdirs.stdout_lines | default([]) }}"
|
||||
loop_control:
|
||||
label: "{{ item }}"
|
||||
register: opatch_apply_results
|
||||
failed_when: false
|
||||
changed_when: false
|
||||
when: dbru_zip is defined and all_subdirs is defined and (all_subdirs.stdout_lines | length) > 0
|
||||
|
||||
- name: Show OPatch apply results (stdout lines)
|
||||
debug:
|
||||
var: opatch_apply_results.results | map(attribute='stdout_lines') | list
|
||||
when: dbru_zip is defined and opatch_apply_results is defined
|
||||
|
||||
- name: Collect failed OPatch applies
|
||||
set_fact:
|
||||
failed_applies: "{{ opatch_apply_results.results | selectattr('rc','ne',0) | map(attribute='item') | list }}"
|
||||
when: dbru_zip is defined and opatch_apply_results is defined
|
||||
|
||||
- name: Fail if any OPatch apply failed
|
||||
fail:
|
||||
msg: "OPatch apply failed in: {{ failed_applies }}"
|
||||
when: dbru_zip is defined and failed_applies is defined and (failed_applies | length) > 0
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user