Code Monkey home page Code Monkey logo

ansible-orapatch's Introduction

ansible-orapatch

Ansible module and playbook for automated Oracle patching

Synopsis

Author: Ivica Arsov
Contact: https://blog.iarsov.com/contact

Last module version: 2.1.0
Last update: 08.10.2023

Python version

As Python 2 support soon is coming to an end (end of 2019), the Orapatch library has been reworked for Python 3

General

The main purpose of the module is to automate the patching process of Oracle database and grid infrastructure binaries with PSUs, BPs and RUs released by Oracle.

One-off patches: It won't work with one-off patches as it's not designed for that. Though, it that can be extended to support one-off patches.

The module will use opatchauto if the Oracle home being patched is grid infrastructure, otherwise it will use standard opatch steps.

The patching is customizable via role's variables definition. For example, you can run just prerequisites without applying the patch, patch binaries without database dictionary changes, skip the OJVM patch, build instant client packages, etc.

The module supports 11g, 12c, 18c and 19c database versions. It should work properly on 10g as well, but I haven't tested it.

Expected actions performed by the module:

The module will identify what database instances, listeners and ASM instances are running.
The module will shutdown all listeners and database instances, only if the home from which services are running is being patched.
The module will start up all previously stopped services after it completes with patching*
The module will skip databases which are not in READ WRITE state**
The module will identify if a given database is in STANDBY or PRIMARY role***
The module always patches GI homes with opatchauto
The module always patches DB homes with opatch
The module will make multiple restarts of the databases and listeners during the process

  • Assuming no error occurred and module did not fail during the patching process.
    ** Even if the databases are specified for patching
    *** Databases in STANDBY role are not patched


Note: If an error is encountered and you restart the process, the module will not automatically start previously stopped services. The module will note stopped services at the beginning of the process and it will leave the services stopped at the end of execution. Due to the nature of how Oracle patching is performed, in some cases if something breaks a manual intervention might be needed. In other words if you restart the Ansible process do not expect to continue from where it stopped.

Opatch has support for "resume" functionality. That's something I can take a look to implement into the module. As of now there is no such option.

Required packages

For this module to work "pexpect" package needs to be installed on the target machine. This is required because in some (most) cases OPatch will (prompt) ask questions. The module uses "pexpect" to fill the answers. If required package is missing the module will fail with a message: module fail: Required "pexpect" (RPM) library not found.

Step-by-step guide

  1. Define the individual hosts or group of hosts in "inventory/hosts" under group [database]

  2. Define the location where patch binaries are extracted with "swlib_path" variable in "roles/orapatch/vars/global.yml"
    The "swlib_path" location needs to be accessible from the target machine.

  3. Define the list of oracle homes to be patched in "roles/orapatch/vars/main.yml"
    For list's variable specification see (below) the "Oracle home list definition format" section.

    3a. Executing the playbook against group of hosts with different oracle home structures

    The list of oracle homes defined in "roles/orapatch/vars/main.yml" is always executed against all hosts defined in the host group. If different targets have different oracle home structure, you can use the "host" variable which can be set for each oracle entry in the list to map the entry to a specific target. With such configuration when the "host" variable is set to a specific target, the entry will be "skipped" for all targets except the matching target.

  4. Check if the patch you want to install is defined in "roles/orapatch/vars/patch_dictionary/patch_dict.yml" file.
    If the patch is not defined, see "Patch metadata format: on how to define patch metadata.

  5. Specify the user which is used to authenticate against target machine in "orapatch.yml" playbook file.

  6. Run the playbook:
    ansible-playbook orapatch.yml -k

    Note: The "-k" option will prompt you to enter the SSH password.
    If you're using SSH keys then "-k" option can be omitted.

Logging

During the whole process, all steps and output are logged in a log file on the target machines.
Currently, there are two logging modes, standard (default) and debug. You switch between the modes with True/False value for the debug variable. In debug mode, more descriptive output is written in the log file.
As an example, if you run OJVM patching with debug mode for 11g you would see the entire output of the post install SQL script that's executed.

At the end of the patching the log file is copied over to the control machine from where the patching started. So, if you patch multiple nodes you will get all log files.

The module by default will prompt for the user to provide root password. It is necessary for opatchauto and it is only applicable when grid infrastructure software is being patched.

Real Application Clusters

The module supports Real Application Clusters (RAC). All you need to do is specify a group of hosts.
There is one tricky moment with clusters. When a node patching is complete, when the CRS is started, the operation is asynchronous, meaning the module will get OK state when it executes crsctl start crs command. At that point from module perspective CRS is up and running. That's why I have implemented a check on every 10 seconds with a timeout of 10 minutes where the CRS is checked if all services are online prior to continue to patch other nodes.

Patch metadata format:

Prior usage, the patches metadata needs to be specified in "vars/patch_dictionary/patch_dict.yml"

25437795: -> patch_id (it's in the name of the file you download from Oracle)
  patch_proactive_bp_id -> patch proactive bundle patch id (if it's bundle patch)
  patch_gi_id: -> Applicable for COMBO (GI) only. GI patch ID. If it's GI only or COMBO DBBP, it is ignored
  patch_db_id -> DB patch ID
  patch_ocw_id -> OCW patch ID (applicable if the patch is COMBO patch)
  patch_ojvm_id -> OJVM patch ID
  patch_acfs_id: -> ACFS patch ID
  patch_dbwlm_id: -> DBWLM path ID
  patch_dir -> patch directory (directory where patch file is extracted)
  file -> patch file name (not used currently)
  only_oh -> whether the patch is for OH binaries only
  desc -> patch description (usually should contain the patch name)

Oracle home list definition format:

Oracle homes and databases which need to be patched can be specified as a list in "vars/main.yml" file.

#
# List of oracle homes and databases to patch.
#
ora_home_list:
  - oracle_owner: -> OS owner of the oracle binaries
    oracle_home_path: -> OH OS path
    oratab_file: -> Absolute path for oratab file. This can be ignored if the global value is set.
    run_only_checks: -> Indicator whether to run onl prereq checks against OH
    patch_id: -> Patch ID of the patch which is to be applied. This module needs to find a match in "vars/patch_dictionary/patch_dict.yml"
    patch_only_oh: -> Indicator whether to patch only OH without the databases (True/False)
    patch_ojvm: -> Indicator whether to apply OJVM patch (applicable if the patch is COMBO) (True/False)
    patch_db_all: -> Indicator whether to apply the patch on all databases after patching the OH ("patch_only_oh" has precedence over "patch_db_all") (True/False)
    patch_db_list: "" -> Comma separated list (in quotes!) of specific databases to patch ("patch_db_all" has precedence over "patch_db_list")
    host: -> It allows the user to specify a mapping to specific host for which this list entry is valid. It's applicable only if the playbook is executed against group of hosts
    backup_oh: -> Indicator whether to backup oracle home binaries (True/False)
    skip: -> Main indicator whether to skip this item or not
    build_client -> Indicator whether to build instant client packages and libraries
    build_client_only -> Indicator to only build instant client packages and libraries
    debug: -> Enables debug mode (True/False)

Example run:

ansible-playbook orapatch.yml -k

License

See LICENSE.md file.

ansible-orapatch's People

Contributors

iarsov avatar pazyp avatar so9000 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

ansible-orapatch's Issues

started getting below error on AIX server.

Thu Aug 4 16:16:11 2022 command: export ORACLE_SID=XXXXX; $ORACLE_HOME/bin/sqlplus -s / as sysdba <<< "startup upgrade"

Thu Aug 4 16:16:11 2022 output:


Thu Aug 4 16:16:11 2022 subprocess error: /bin/sh: syntax error at line 1 : `<' unexpected

Thu Aug 4 16:16:11 2022 Module fail: /bin/sh: syntax error at line 1 : `<' unexpected


Thu Aug 4 16:16:11 2022 orapatch session end

Only start one database after ojvm patch

one oracle home has muliple databases. its stopped all databases but only run datapatch on one database and start it. missing datapatch on others and kept it down. no errors reported

Failure to patch 19C

When running your scripts I am getting this error on 19C. I can't tell if this is a opatch issue or something else.

TASK [orapatch : Check OPatch minimum version] *********************************
task path: /tmp/awx_2708_bgxds5aj/project/AWX-Templates/oracle/roles/orapatch/tasks/main.yml:40
failed: [vlfth-dbora19c] (item={'oracle_owner': 'oracle', 'oracle_home_path': '/u01/app/oracle/product/19.0.0/dbhome_1', 'oratab_file': '/etc/oratab', 'run_only_checks': False, 'debug': False, 'patch_id': '32218454', 'patch_only_oh': False, 'patch_ojvm': True, 'patch_db_all': True, 'patch_db_list': 'dbtcity', 'host': 'vlfth-dbora19c', 'backup_oh': False, 'skip': False}) => {
"ansible_loop_var": "item",
"changed": false,
"item": {
"backup_oh": false,
"debug": false,
"host": "vlfth-dbora19c",
"oracle_home_path": "/u01/app/oracle/product/19.0.0/dbhome_1",
"oracle_owner": "oracle",
"oratab_file": "/etc/oratab",
"patch_db_all": true,
"patch_db_list": "dbtcity",
"patch_id": "32218454",
"patch_ojvm": true,
"patch_only_oh": false,
"run_only_checks": false,
"skip": false
},
"msg": "Patch '32218454'not found!'32218454'"

here is what is in the dictionary file

Defined Oracle patches

patch_dict:

#""" 19.10.0.0.0 """
32218454:
patch_proactive_bp_id:
patch_gi_id:
patch_db_id: 32218454
patch_ocw_id:
patch_ojvm_id:
patch_acfs_id:
patch_dbwlm_id:
patch_dir: /u01/app/oracle/product/19.0.0/dbhome_1/32218454
file: p32218454_190000_Linux-x86-64.zip
only_oh: False
desc: "Database Release Update 19.0.0.0.0"

Error when starting or ending Logger session

Error occurs on both functions start or end logging, occurs on multiple machines.

"argument 'oracle_home' is of type <class 'NoneType'> and we were unable to convert to path: 'None' is not a string and conversion is not allowed"

oracle_home_path is defined in host_vars file as:
ora_home_list:
- oracle_owner: oracle
oracle_home_path: /oracle_base/app/oracle/product/19.0.0.0/dbhome_1

Having issues it is saying can't find Patch XXXXX

TASK [orapatch : Check OPatch minimum version]

{
"msg": "Patch '32218454'not found!'32218454'",
"_ansible_no_log": false,
"changed": false,
"item": {
"oracle_owner": "oracle",
"oracle_home_path": "/u01/app/oracle/product/19.0.0/dbhome_1",
"oratab_file": "/etc/oratab",
"run_only_checks": false,
"debug": true,
"patch_id": "32218454",
"patch_only_oh": false,
"patch_ojvm": true,
"patch_db_all": true,
"patch_db_list": "dbtcity",
"host": "vlfth-dbora19c",
"backup_oh": false,
"skip": false
},
"ansible_loop_var": "item",
"_ansible_item_label": {
"oracle_owner": "oracle",
"oracle_home_path": "/u01/app/oracle/product/19.0.0/dbhome_1",
"oratab_file": "/etc/oratab",
"run_only_checks": false,
"debug": true,
"patch_id": "32218454",
"patch_only_oh": false,
"patch_ojvm": true,
"patch_db_all": true,
"patch_db_list": "dbtcity",
"host": "vlfth-dbora19c",
"backup_oh": false,
"skip": false
}

I also looked at the code but where does the Check Min Opatch Version know which version it should be looking for. I didn't see that in any of the code.

I am not feeding a root password because I am use AWX accessing the server as root and then becoming oracle userid.

"msg": "[orapatch] module fail: Argument(s) Error... Patch base location is not valid.\n\n", "rc": 245

Hi

I am trying to use this module to patch 18c database present in the target machine, while I running the playbook i am getting the below error. Please check and help me to get this resolved.

TASK [orapatch : Check OPatch minimum version] *************************************************************************************************************************
[WARNING]: Module did not set no_log for root_password

failed: [104.45.3.126] (item={u'patch_db_list': u'', u'skip': False, u'run_only_checks': None, u'patch_id': 29708235, u'oracle_home_path': u'/mnt/resource/oracle/db_1', u'patch_db_all': True, u'debug': False, u'oracle_owner': u'oracle', u'patch_ojvm': True, u'patch_only_oh': False, u'host': None, u'oratab_file': None, u'backup_oh': False}) => {"ansible_loop_var": "item", "changed": false, "item": {"backup_oh": false, "debug": false, "host": null, "oracle_home_path": "/mnt/resource/oracle/db_1", "oracle_owner": "oracle", "oratab_file": null, "patch_db_all": true, "patch_db_list": "", "patch_id": 29708235, "patch_ojvm": true, "patch_only_oh": false, "run_only_checks": null, "skip": false}, "msg": "[orapatch] module fail: Argument(s) Error... Patch base location is not valid.\n\n", "rc": 245}

The patching gets stuck

Hi,
I have been trying to apply the Jul 2019 patch to a 12.1 standalone Database.
This is a combo patch with DB as well as OJVM patches.
It has applied the DB patch and updated the dictionary which i can query and confirm is all fine.
But it is getting stuck indefinitely at the below statement after applying the OJVM patch to the Oracle Home. I don't see any session at the backend as well to see if it is doing anything.

==============================================
PATCH_DB_OJVM => BUILD_INSTANCE_LIST

Wed 21 Oct 2020 09:38:02 AM EDT command: ps -ef | grep -iw [o]ra_pmon_orcl | wc -l
Wed 21 Oct 2020 09:38:02 AM EDT ORACLE_HOME set to to '/u01/app/oracle/product/12.1/db_1'
Wed 21 Oct 2020 09:38:02 AM EDT command: export ORACLE_SID=orcl; $ORACLE_HOME/bin/sqlplus -s / as sysdba @/tmp/orapatch_scripts/get_db_metadata

Is there any help you could provide in this regard?

Thanks,
Umesh

Patching 19c fails

While trying to apply 19 OJVM+DBRSU patch, we are getting the following error. We added some debug statements to print the variables and patch_dict variable is coming in as None. It seems like the task_vars[patch_dict] is set to None too. Any idea why are we getting this issue? Thanks for your help.

        print("Before try")
        try:

            print("Inside try")
            patch_id = int(db_item["patch_id"])
            print(patch_id)
            patch_dict = task_vars["patch_dict"]
            **print(task_vars["patch_dict"])**

            print("Before patch_item")
            patch_item = patch_dict[patch_id]
            print(patch_item)
            patch_item["patch_id"] = patch_id
            print(patch_item["patch_id"])
            args["patch_item"] = patch_item
            print("Last line in try block")

TASK [orapatch : Check OPatch minimum version] ***************************************************************************************************************************************************************************************************************
task path: /apps/stage/ANSIBLE_AUTOMATION/ansible-orapatch-master/roles/orapatch/tasks/main.yml:40
Before try
Inside try
34773489
None
Before patch_item
failed: [db3s11.shared.musw1-ep01-core.np.norton.com] (item={u'patch_db_list': u'DB3S1', u'patch_ojvm': True, u'skip': False, u'run_only_checks': True, u'host': u'db3s11.shared.musw1-ep01-core.np.norton.com', u'patch_only_oh': True, u'oratab_file': u'/etc/oratab', u'oracle_owner': u'oracle', u'patch_db_all': True, u'oracle_home_path': u'/apps/oh/19c/odb', u'build_client_only': False, u'debug': True, u'build_client': False, u'patch_id': 34773489, u'backup_oh': False}) => {
"ansible_loop_var": "item",
"changed": false,
"item": {
"backup_oh": false,
"build_client": false,
"build_client_only": false,
"debug": true,
"host": ",
"oracle_home_path": "/apps/oh/19c/odb",
"oracle_owner": "oracle",
"oratab_file": "/etc/oratab",
"patch_db_all": true,
"patch_db_list": "",
"patch_id": 34773489,
"patch_ojvm": true,
"patch_only_oh": true,
"run_only_checks": true,
"skip": false
},
"msg": "Patch '34773489'not found!'NoneType' object has no attribute 'getitem'"
}

TASK [orapatch : [SYSTEM] End logger session] ****************************************************************************************************************************************************************************************************************
task path: /apps/stage/ANSIBLE_AUTOMATION/ansible-orapatch-master/roles/orapatch/tasks/main.yml:154

Needs to know if this code is compatible with ansible 2.8 and python 3.6

hi iarsov,
I am getting below error .

error:

-->[Applicable if you patch Grid Infrastructure]<--
Enter root password (press enter to skip):
Enter root password again (press enter to skip):

PLAY [Patch oracle software] ********************************************************************************************************************************

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

TASK [assert] ***********************************************************************************************************************************************
ok: [host2] => {
    "changed": false,
    "msg": "All assertions passed"
}

TASK [orapatch : [SYSTEM] Include vars] *********************************************************************************************************************
ok: [host2]

TASK [orapatch : [SYSTEM] Push sql scripts] *****************************************************************************************************************
ok: [host2]

TASK [orapatch : [SYSTEM] Ensure 'orapatch' log file exists] ************************************************************************************************
ok: [host2]

TASK [orapatch : [SYSTEM] Start logger session] *************************************************************************************************************
fatal: [host2]: FAILED! => {"msg": "Unable to import orapatch due to invalid syntax"}

TASK [orapatch : [SYSTEM] End logger session] ***************************************************************************************************************
fatal: [host2]: FAILED! => {"msg": "Unable to import orapatch due to invalid syntax"}

PLAY RECAP **************************************************************************************************************************************************
host2               : ok=5    changed=0    unreachable=0    failed=2    skipped=0    rescued=0    ignored=0

my environment:

[ansible@ip-host1 ansible-orapatch]$ python3 --version
Python 3.6.8
[ansible@ip-host1  ansible-orapatch]$ python2 --version
Python 2.7.16
[ansible@ip-host1  ansible-orapatch]$ ansible --version
ansible 2.8.5
  config file = /home/ansible/ansible-orapatch/ansible.cfg
  configured module search path = ['/home/ansible/ansible-orapatch/library']
  ansible python module location = /usr/local/lib/python3.6/site-packages/ansible
  executable location = /usr/local/bin/ansible
  python version = 3.6.8 (default, Apr  3 2019, 17:26:03) [GCC 8.2.1 20180905 (Red Hat 8.2.1-3)]

Orapatch problematic code:

from __future__ import (absolute_import, division, print_function)
__metaclass__ = type

from ansible.plugins.action import ActionBase

Patching fails for 11.2 version due to emocmrsp

Ivica,
I was trying the module to patch 11.2.0.4 database home and is failing with the below error.
As per MOS 2161861.1 this is now deprecated and ocmrsp is no longer required.

Thu 29 Oct 2020 03:45:47 AM EDT ORACLE_HOME set to to '/u01/app/oracle/product/11.2.0.4/dbhome_1'
Thu 29 Oct 2020 03:45:47 AM EDT command: /u01/app/oracle/product/11.2.0.4/dbhome_1/OPatch/ocm/bin/emocmrsp -no_banner -output /tmp/orapatch_ocm_2020-10-29_03-45-47AM.rsp
Thu 29 Oct 2020 03:45:47 AM EDT The command was not found or was not executable: /u01/app/oracle/product/11.2.0.4/dbhome_1/OPatch/ocm/bin/emocmrsp.
Thu 29 Oct 2020 03:45:47 AM EDT ExceptionPexpect
Thu 29 Oct 2020 03:45:47 AM EDT Module fail: Traceback (most recent call last):
File "/tmp/ansible_orapatch_payload_M_Qgfy/ansible_orapatch_payload.zip/ansible/modules/orapatch.py", line 2051, in main
File "/tmp/ansible_orapatch_payload_M_Qgfy/ansible_orapatch_payload.zip/ansible/modules/orapatch.py", line 461, in init
File "/tmp/ansible_orapatch_payload_M_Qgfy/ansible_orapatch_payload.zip/ansible/modules/orapatch.py", line 507, in gen_ocm_file
File "/tmp/ansible_orapatch_payload_M_Qgfy/ansible_orapatch_payload.zip/ansible/modules/orapatch.py", line 622, in run_os_command
File "/usr/lib/python2.7/site-packages/pexpect.py", line 221, in run
child = spawn(command, timeout=timeout, maxread=2000, logfile=logfile, cwd=cwd, env=env)
File "/usr/lib/python2.7/site-packages/pexpect.py", line 429, in init
self._spawn (command, args)
File "/usr/lib/python2.7/site-packages/pexpect.py", line 516, in _spawn
raise ExceptionPexpect ('The command was not found or was not executable: %s.' % self.command)
ExceptionPexpect: The command was not found or was not executable: /u01/app/oracle/product/11.2.0.4/dbhome_1/OPatch/ocm/bin/emocmrsp.

Would changing the system parameter to include version 11 as a supported version help in fixing the error?

Thanks,
Umesh

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.