In the previous ALIS article, we turned an Oracle AutoUpgrade plan into a configuration and an ordered runbook. The next step was fairly obvious: make that plan executable with Ansible.
ALIS now exports an Ansible ZIP for patching an existing Oracle database. Configure the operation in the browser, download the bundle, review it and run it from your controller. AutoUpgrade performs the Oracle work; Ansible stages the files, runs the phases and brings back the evidence.
What the export supports
The current exporter handles one existing Linux single-instance database with OUTOFPLACE patching. You provide different source and target Oracle homes. The target home can be prepared before the maintenance window; deployment then moves and patches the database.
RAC, RAC One Node, SEHA, Data Guard, upgrades and migrations require their own coordination and are outside this export (for now). ALIS explains why the download button is unavailable when the selected plan is unsupported. The runner also checks the actual database topology on the server.
ALIS still runs locally in your browser. Generating the ZIP does not connect to the database or execute a patch. Execution starts when you run the playbooks on your controller.
Build the bundle in ALIS
- Open ALIS and select the AutoUpgrade profile matching the JAR you will use. This lab uses
26.6.260925. - In Plan, choose Patch existing databases and keep one database job.
- In Environment, select Linux or Oracle Linux 9, then Single instance.
- Set the SID, source home, target home, media folder, log directory and patch policy. Keep the patching method
OUTOFPLACE. Review the configuration and any validation findings. - In Runbook → Automate with Ansible, fill in the execution host, SSH user, Oracle software owner, dedicated working directory and Python executable. Review the timeout and polling interval.
- Click Download Ansible bundle .zip, extract it and start with its
README.md.
What is inside the ZIP?
alis-ansible/
├── README.md
├── alis-runbook.md
├── ansible.cfg
├── inventory.yml
├── host_vars/oracle_db.yml
├── files/
│ ├── autoupgrade.cfg
│ ├── autoupgrade.home.cfg
│ ├── plan.json
│ └── runner.py
├── prepare.yml
├── analyze.yml
├── download.yml
├── create_home.yml
├── deploy.yml
├── verify.yml
├── patch.yml
├── tasks/
│ ├── prepare.yml
│ └── run.yml
├── test-local.yml
└── tests/simulator.pyplan.json records the selected AutoUpgrade profile, paths and file hashes. The runner checks that the JAR and configurations match that plan. It also keeps recovery state on the execution host, so another invocation can recognise verified phases.
The home configuration allows home creation to be separated from database deployment. If you enable output Gold Image packaging, the exporter adapts that configuration to avoid capturing the output twice. In this lab, the two configuration files are identical.
The lab: ORCLSE, 19.23 → 19.32
The controller is my Mac. Ansible connects to the database server as oracle, which is also the Oracle software owner. The database is a Standard Edition CDB with CDB$ROOT, PDB$SEED and ORCLSE1.
| Setting | This run |
|---|---|
| Execution host | 10.10.10.201 |
| SID | ORCLSE |
| Source version | 19.23.0.0.0 |
| Resolved target version | 19.32.0.0.260721 |
| Source home | /opt/oracle/product/19c/dbhome_se |
| Target home | /opt/oracle/product/19.32/dbhome_se |
| AutoUpgrade JAR | /home/oracle/autoupgrade/autoupgrade.jar |
| Ansible work directory | /home/oracle/alis-patch |
This is the actual files/autoupgrade.cfg used by the run:
# Generated with ALIS
# AutoUpgrade profile: 26.6.260925
# Follow the generated runbook for this operation and execution host.
global.global_log_dir=/home/oracle/autoupgrade/logs
global.keystore=/home/oracle/autoupgrade/keys
upg1.sid=ORCLSE
upg1.source_home=/opt/oracle/product/19c/dbhome_se
upg1.target_home=/opt/oracle/product/19.32/dbhome_se
upg1.target_version=19
upg1.folder=/home/oracle/autoupgrade/bin
upg1.download=YES
upg1.patch=RECOMMENDED
upg1.gold_image=YES
upg1.timezone_upg=YES
The target directory name does not select the RU. This run uses the unpinned RECOMMENDED policy; the native reports and inventory show that it resolved to 19.32. To request that RU explicitly in a new cycle, use upg1.patch=RECOMMENDED:19.32. Make that decision before exporting and starting the cycle; preserve the original configuration for an active run.
gold_image=YES selects Oracle-supplied Gold Image input media. It is distinct from create_gold_image, which packages a target home as output. Here, AutoUpgrade downloaded a 19.32 image and used it to create the new home.
Prepare the controller and test locally
The bundle's documented controller setup uses Python 3.12 or newer and ansible-core 2.21. Run these commands on the controller, from the extracted directory:
cd /Users/inter/Downloads/alis-ansible
python3 -m venv ~/.venvs/alis-ansible
source ~/.venvs/alis-ansible/bin/activate
python3 -m pip install 'ansible-core>=2.21,<2.22'
ansible-playbook test-local.yml --syntax-check
ansible-playbook test-local.ymlThe simulator runs the real playbook sequence against temporary fake tools on localhost. Expect failed=0 and unreachable=0. Its results go to artifacts/localhost/. This validates orchestration; real Oracle results come from the separate artifacts/oracle_db/ directory.
The real playbooks reject --check. Use the simulator to exercise their flow, including failures:
ansible-playbook test-local.yml -e alis_test_failure=rootFor that intentional failure, expect failed=1 and no deployment in the sandbox. If macOS reports an invalid locale, set LANG and LC_ALL to an available UTF-8 locale; this controller uses en_US.UTF-8.
Prepare the database host
The host needs SSH access, Python 3.9 or newer for this Ansible version, a Java runtime supported by the selected AutoUpgrade JAR and the Oracle installation prerequisites. Put the exact JAR at the path in files/plan.json; the ZIP does not include Oracle software or your credentials.
Prepare the media, logs and keystore directories with the right ownership. Use a dedicated Ansible work directory and a dedicated AutoUpgrade global log directory for each new patch cycle. The paths below belong to this existing lab cycle.
For online downloads, prepare the AutoUpgrade auto-login wallet interactively on the database host, as the Oracle software owner. After placing the reviewed configuration on that host, use the runbook's password-loader procedure:
# Database host, as oracle; use the reviewed configuration's actual path.
java -jar /home/oracle/autoupgrade/autoupgrade.jar \
-patch -config /path/to/autoupgrade.cfg -load_passwordAt the MOS> prompt, use add -user YOUR_MOS_USER, enter the password at the hidden prompt, then list, save and exit. Choose auto-login when prompted. The unattended runner checks for cwallet.sso in the configured keystore. Keep passwords and tokens out of ALIS, YAML and JSON.
Arrange the supported sudo execution of installation root scripts before starting an unattended run. The lab connects as oracle; alis_become: false means Ansible already runs as the software owner. It does not remove the requirement to execute root scripts during installation.
Review backup and recovery arrangements and the maintenance window. The actual precheck report contains a STANDARD_EDITION warning: guaranteed restore points are unavailable for this edition. This lab needs a backup-based recovery plan, and AutoUpgrade does not automatically restore an external backup.
Review the inventory and execution settings
Here is the lab's inventory.yml. Replace the host and user with your own values when creating your bundle:
---
all:
children:
oracle_patch:
hosts:
oracle_db:
ansible_host: !unsafe "10.0.0.201"
ansible_user: !unsafe "oracle"
And its host_vars/oracle_db.yml:
---
alis_oracle_user: !unsafe "oracle"
alis_become: false
alis_work_dir: !unsafe "/home/oracle/alis-patch"
alis_python: !unsafe "/usr/bin/python3.12"
ansible_python_interpreter: !unsafe "/usr/bin/python3.12"
alis_timeout: 32400
alis_poll_interval: 15
alis_resume: false
The generated ansible.cfg selects this inventory and keeps SSH host-key checking enabled. Test connectivity from the controller:
ansible oracle_patch -m ansible.builtin.pingThe timeout here is nine hours per operation, with a 15-second polling interval. The tasks use Ansible's async execution with positive polling: Ansible waits for each operation before proceeding to the next phase. Set the timeout generously for your environment; expiration can interrupt the task.
Run the patch cycle
Once the prerequisites and maintenance plan are ready, start the complete sequence from the controller:
cd /Users/inter/Downloads/alis-ansible
source ~/.venvs/alis-ansible/bin/activate
export LANG=en_US.UTF-8 LC_ALL=en_US.UTF-8
ansible-playbook patch.ymlpatch.yml imports six playbooks in order:
---
# Complete patch cycle; each stage must succeed before the next starts.
- ansible.builtin.import_playbook: prepare.yml
vars:
alis_cycle: true
- ansible.builtin.import_playbook: analyze.yml
vars:
alis_cycle: true
- ansible.builtin.import_playbook: download.yml
vars:
alis_cycle: true
- ansible.builtin.import_playbook: create_home.yml
vars:
alis_cycle: true
- ansible.builtin.import_playbook: deploy.yml
vars:
alis_cycle: true
- ansible.builtin.import_playbook: verify.yml
vars:
alis_cycle: true
| Phase | What it does |
|---|---|
prepare | Stages the bundle and checks the JAR, database identity, active source home, topology and media prerequisites. |
analyze | Runs native AutoUpgrade analysis and verifies readiness reports and checklists. |
download | Downloads and verifies media and checksums. With download=NO, validates staged media. |
create_home | Installs and patches the target home; verifies native installation/root stages and binary inventory. The database stays on the source home. |
deploy | Moves and patches the database using AutoUpgrade, then verifies the database result. |
verify | Checks the active home, database and container states, binary inventory and SQL patch registry again. |
The full playbook continues automatically from one successful phase to the next, including deployment. There is no interactive approval between phases. Add -K when Ansible privilege escalation requires a password; AutoUpgrade's installation root-script prerequisites still need their own preparation.
To prepare the new home before downtime and inspect the results before deployment, run the individual playbooks instead:
ansible-playbook prepare.yml
ansible-playbook analyze.yml
ansible-playbook download.yml
ansible-playbook create_home.yml
# Review preparation results. During the maintenance window:
ansible-playbook deploy.yml
ansible-playbook verify.ymlKeep the same bundle and state throughout the cycle. With download=YES, native validation in analyze or deploy can also fetch or check media. Use one execution path for a cycle so that Ansible's recorded state remains consistent with the work performed.
What the completed run showed
The lab's analysis job was 100, for ORCLSE. Its PRECHECKS phase completed 133 checks across three containers, with no check execution errors. Findings include information, recommendations and warnings that remain available for review.
That distinction matters when reading native JSON: checksFailed also contains checks whose checklist severity is INFO, RECOMMEND or WARNING. The runner reads the associated checklists and stops on ERROR, execution errors or incomplete checks. It also rejects missing, stale or mismatched reports. A zero Java return code alone does not establish that a phase succeeded.
Home creation used job 101, named create_home_1. That name describes the home-preparation job; database jobs use ORCLSE. All eleven native stages completed, including EXTRACT, INSTALL, OH_PATCHING and ROOTSH. The recorded native interval was 12:13:10–12:31:59, about 19 minutes. That is home-preparation time, not database downtime.
The verified target-home inventory contains, among other patches:
39222882;OJVM RELEASE UPDATE: 19.32.0.0.260721 (39222882)
39657094;DATAPUMP BUNDLE PATCH 19.32.0.0.0
39526364;OCW RELEASE UPDATE 19.32.0.0.0 (39526364)
39472050;Database Release Update : 19.32.0.0.260721 (39472050)This is an excerpt from the real inventory.log. The full inventory includes additional fixes. The post-create-home database check still showed the source database open as PRIMARY, with ORCLSE1 read/write and the seed read-only.
Deployment completed as job 102 on 5 October 2026. The native run started at 13:39:51 CEST and finished at 15:05:06 CEST: approximately 1 hour 25 minutes. AutoUpgrade reported totalPercentCompleted=100, with all eight stages successful and no stage errors.
| Native deployment stage | Recorded duration | Result |
|---|---|---|
PRECHECKS | 1 min 3 sec | Complete |
PREFIXUPS | 8 min 15 sec | Complete |
DB_PATCHING | 1 hr 11 min 31 sec | Complete |
POSTCHECKS | 3 sec | Complete |
POSTFIXUPS | 4 min 21 sec | Complete |
The remaining stages — PENDING, PREACTIONS and POSTACTIONS — also completed successfully. These are measurements from this lab; the native stage timings do not measure application downtime.
After deployment, ORCLSE was OPEN / PRIMARY / READ WRITE, and V$INSTANCE.VERSION_FULL reported 19.32.0.0.0. PMON was running /opt/oracle/product/19.32/dbhome_se/bin/oracle. Direct reads of the SQL patch registry in each container confirmed both the Database RU and OJVM:
Next: useful progress in the Ansible terminal
We are now working on progress and status reporting for future Ansible exports. During a long operation, the current terminal can show repeated ASYNC POLL messages that only tell you the process is still running. The new reporting will read AutoUpgrade's native progress and status reports and show what the job is doing.
The planned output includes the operation, job number, current stage, stage progress and overall job progress. An illustrative message would look like this:
deploy | job 102 | DB_PATCHING 42% | total 68%This is an example of the intended format, not a captured result from the completed run. Updates will appear in the same terminal after ansible-playbook patch.yml, without a separate monitoring command. Periodic activity messages will also make it clear when a lengthy stage is still running even though its percentage has not changed.
The percentage will describe progress reported by AutoUpgrade. Phase completion and success will still depend on the native reports, checklists, inventory and SQL patch verification. This reporting is being developed for newly generated bundles and subsequent runs.
Read results and resume a failed cycle
Fetched evidence goes to artifacts/oracle_db/ on the controller. During a long-running task, those copies can lag behind the server because fetching happens after the task returns. The server has current runner results under /home/oracle/alis-patch/results/, recovery state in /home/oracle/alis-patch/state.json and native reports under:
/home/oracle/autoupgrade/logs/cfgtoollogs/patch/auto/status/
/home/oracle/autoupgrade/logs/ORCLSE/102/After fixing a failed phase, preserve the original bundle, JAR, configuration, media, logs and recovery state, then request resume explicitly:
ansible-playbook patch.yml -e alis_resume=trueVerified phases are skipped. The failed phase is resumed where supported, and remaining phases start in order; a failed download is rerun without a native job-resume flag. A normal invocation also recognises already verified preparation phases, as happened in this lab after their reports were rechecked.
If native deployment completed but final verification failed, correct the verification problem and run ansible-playbook verify.yml. The runner checks the existing deployment and does not repeat the database patch operation merely to retry verification.
Final verification checks that PMON uses the target home, the database is open as a primary, containers are open and the latest SQL patch actions contain successful APPLY entries for the target-home RU/OJVM patches in every container. Review the resulting verification.json, sqlpatch.log and native reports, then complete your application and service checks.
Try it on your patch plan
ALIS now carries the plan through to an executable bundle: review the settings, test the orchestration locally, prepare the target home and run the database phase in your maintenance window. The bundle keeps the configuration and evidence together, which makes the next question — “what actually happened?” — much easier to answer.
Open ALIS, select Patch existing databases and explore Automate with Ansible. The generated README and runbook travel with your exact plan. The source code and Ansible templates are available on GitHub.
FIELD NOTES