diff --git a/changelogs/fragments/autoupgrade-update.yml b/changelogs/fragments/autoupgrade-update.yml new file mode 100644 index 000000000..8f98854e9 --- /dev/null +++ b/changelogs/fragments/autoupgrade-update.yml @@ -0,0 +1,7 @@ +--- +minor_changes: + - "autoupgrade: autoupgrade_run_local executes AutoUpgrade on the Ansible controller (default true) or on the target host (false) for all task files" + - "autoupgrade: install.yml checks the Python module pexpect on the host executing AutoUpgrade (pexpect is not installed by the role)" + - "autoupgrade: install.yml creates oracle_base on the target host - AutoUpgrade can be used before the installation of the Oracle software" + - "autoupgrade: autoupgrade_download_latest downloads the latest autoupgrade.jar on the Ansible controller, or on the target host when oracle_sw_copy is false" + - "autoupgrade: autoupgrade_download_gold_image_rename renames downloaded Gold Images to autoupgrade_download_gold_image_prefix + release (e.g. db_home_19.32.zip) and creates a symlink with the original filename" diff --git a/doc/guides/autoupgrade.adoc b/doc/guides/autoupgrade.adoc index f67a1c06d..1107d9f5f 100644 --- a/doc/guides/autoupgrade.adoc +++ b/doc/guides/autoupgrade.adoc @@ -27,7 +27,7 @@ The variables of the role are described in link:../../roles/autoupgrade/README.m * Database server: e.g. the JDK from an `ORACLE_HOME` (`autoupgrade_java_home`) * Ansible controller: `java` from `PATH` or `autoupgrade_local_java_home` - Python module `pexpect` on the host executing AutoUpgrade for the keystore management - (used by `ansible.builtin.expect`) + (used by `ansible.builtin.expect`). It is checked by `install.yml`, but not installed by the role. - My Oracle Support account (`mos_username`, `mos_password`) for downloading patches - Downloads with AutoUpgrade are supported for the releases 19, 21, 23 and 26 (AutoUpgrade 26.6) @@ -60,13 +60,14 @@ Each area of AutoUpgrade has its own task file, which must be called with `tasks [options="header,footer"] |======================= |Playbook |Description -|`playbooks/autoupgrade_install.yml` | Install AutoUpgrade on the database servers. `hostgroup` is mandatory. +|`playbooks/autoupgrade_install.yml` | Install AutoUpgrade. `hostgroup` is mandatory. Use `autoupgrade_run_local: false` for the database servers. |`playbooks/autoupgrade_download_patches.yml` | Download patches with AutoUpgrade. |======================= .Install AutoUpgrade on database servers ---- -ansible-playbook -i inventory/ -e hostgroup=dbservers playbooks/autoupgrade_install.yml +ansible-playbook -i inventory/ -e hostgroup=dbservers -e autoupgrade_run_local=false \ + playbooks/autoupgrade_install.yml ---- .Download patches and the latest autoupgrade.jar @@ -77,21 +78,41 @@ ansible-playbook -i inventory/ -e hostgroup=dbservers -e autoupgrade_download_la === Execution on Ansible controller or database server -AutoUpgrade is always executed on the database server as `oracle_user` - with one exception: - -The download of patches (`download_patches.yml`) including the keystore and the installation needed for the download -is executed on the Ansible controller by default (`autoupgrade_download_run_local: true`). +`autoupgrade_run_local` defines, where AutoUpgrade is executed. +The switch is valid for all task files. .Execution of AutoUpgrade [options="header,footer"] |======================= -|Task file |`autoupgrade_download_run_local` |Executed on |Directory |Java -|`install.yml` (direct call) | ignored | database server as `oracle_user` | `autoupgrade_home` | `autoupgrade_java_home` -|`download_patches.yml` | `true` (default) | Ansible controller, `run_once`, no `become` | `autoupgrade_local_home` | `autoupgrade_local_java_home` -|`download_patches.yml` | `false` | database server as `oracle_user` | `autoupgrade_home` | `autoupgrade_java_home` +|`autoupgrade_run_local` |Executed on |Directory |Java +|`true` (default) | Ansible controller, `run_once`, no `become` | `autoupgrade_local_home` | `autoupgrade_local_java_home` +|`false` | target host as `oracle_user` | `autoupgrade_home` | `autoupgrade_java_home` |======================= -IMPORTANT: The download on the Ansible controller is executed only once (`run_once`) with the variables +IMPORTANT: AutoUpgrade is executed on the Ansible controller by default. + +Set `autoupgrade_run_local: false` for the execution on the database servers, e.g. for the installation on the database servers. + +.Install AutoUpgrade on the database servers and download patches on the Ansible controller +---- +ansible-playbook -i inventory/ -e hostgroup=dbservers -e autoupgrade_run_local=false \ + playbooks/autoupgrade_install.yml + +ansible-playbook -i inventory/ -e hostgroup=dbservers playbooks/autoupgrade_download_patches.yml +---- + +The host executing AutoUpgrade needs: + +- Java (see `autoupgrade_java_home` / `autoupgrade_local_java_home`) +- Python module `pexpect` for the Python interpreter used by Ansible (keystore console). + `install.yml` checks it at the beginning and fails with a clear message. + The role does not install `pexpect` - install it e.g. with the package `python3-pexpect` or with `pip`. +- With `autoupgrade_run_local: false`: `autoupgrade_download_dir` must be a directory on the target host, + writable for `oracle_user`. The default `oracle_sw_source_local` is a directory on the Ansible controller. +- With `autoupgrade_run_local: false`: `oracle_user` must exist (playbook `os`). + `oracle_base` and `oracle_base/cfgtoollogs` are created by `install.yml` with the same attributes as in `oraswdb_install`. + AutoUpgrade can be used before the installation of the Oracle software, e.g. for downloading the patches. + +IMPORTANT: With `autoupgrade_run_local: true` the tasks are executed only once (`run_once`) with the variables of the *first host* in the play. + `oracle_sw_patches`, `db_homes_installed`, `db_homes_config`, `oracle_install_version_gi` and `autoupgrade_download_patches` must be the same for all hosts in the play - e.g. defined in `group_vars/all` @@ -113,8 +134,19 @@ On the Ansible controller `oracle_sw_copy` is ignored and the file is always tak ==== Download the latest version `autoupgrade_download_latest: true` downloads the latest `autoupgrade.jar` from Oracle (`autoupgrade_jar_url`) -into the software repository on the Ansible controller before the installation. -The download is done once (`run_once`) and requires `is_sw_source_local: true`. +into the software repository before the installation. +The target depends on the location of the installation media: + +.Target for the download of the latest version +[options="header,footer"] +|======================= +|Installation media |Download on |Target +|`oracle_sw_copy: true` or `autoupgrade_run_local: true` | Ansible controller, `run_once`, no `become`. Requires `is_sw_source_local: true`. | `autoupgrade_jar_filesource` or `oracle_sw_source_local`/`autoupgrade_jar` +|`oracle_sw_copy: false` | target host as `oracle_user` | `autoupgrade_jar_filesource` or `oracle_stage_remote`/`autoupgrade_jar` +|======================= + +IMPORTANT: With `oracle_sw_copy: false` the target directory must exist on the target host and must be writable for `oracle_user`. + +On a shared NFS directory each host downloads the file. ==== Update an existing installation @@ -123,7 +155,7 @@ An existing `autoupgrade.jar` is not replaced by default. + .Update AutoUpgrade on all database servers with the latest version from Oracle ---- -ansible-playbook -i inventory/ -e hostgroup=dbservers \ +ansible-playbook -i inventory/ -e hostgroup=dbservers -e autoupgrade_run_local=false \ -e autoupgrade_download_latest=true -e autoupgrade_force_update=true \ playbooks/autoupgrade_install.yml ---- diff --git a/roles/autoupgrade/README.md b/roles/autoupgrade/README.md index ab5f2fbaa..210134337 100644 --- a/roles/autoupgrade/README.md +++ b/roles/autoupgrade/README.md @@ -18,10 +18,11 @@ Each area of AutoUpgrade has its own task file, which must be called with `tasks - [autoupgrade_download_dir](#autoupgrade_download_dir) - [autoupgrade_download_filename_regex](#autoupgrade_download_filename_regex) - [autoupgrade_download_gold_image](#autoupgrade_download_gold_image) + - [autoupgrade_download_gold_image_prefix](#autoupgrade_download_gold_image_prefix) + - [autoupgrade_download_gold_image_rename](#autoupgrade_download_gold_image_rename) - [autoupgrade_download_latest](#autoupgrade_download_latest) - [autoupgrade_download_patches](#autoupgrade_download_patches) - [autoupgrade_download_platform](#autoupgrade_download_platform) - - [autoupgrade_download_run_local](#autoupgrade_download_run_local) - [autoupgrade_download_supported_releases](#autoupgrade_download_supported_releases) - [autoupgrade_download_use_oracle_sw_patches](#autoupgrade_download_use_oracle_sw_patches) - [autoupgrade_force_update](#autoupgrade_force_update) @@ -40,6 +41,7 @@ Each area of AutoUpgrade has its own task file, which must be called with `tasks - [autoupgrade_local_home](#autoupgrade_local_home) - [autoupgrade_local_java_home](#autoupgrade_local_java_home) - [autoupgrade_log_dir](#autoupgrade_log_dir) + - [autoupgrade_run_local](#autoupgrade_run_local) - [Discovered Tags](#discovered-tags) - [Dependencies](#dependencies) - [License](#license) @@ -96,14 +98,52 @@ autoupgrade_download_gold_image: '' autoupgrade_download_gold_image: "NO" ``` +### autoupgrade_download_gold_image_prefix + +Prefix for the new filename of a Gold Image (`autoupgrade_download_gold_image_rename: true`). + +#### Default value + +```YAML +autoupgrade_download_gold_image_prefix: db_home_ +``` + +### autoupgrade_download_gold_image_rename + +Rename downloaded Gold Images after the download. + +AutoUpgrade creates unique filenames with a timestamp, e.g. `db_goldimage_19_32_20261021112350.zip`. +The file is renamed to `autoupgrade_download_gold_image_prefix` + release + `.zip`: + +| Gold Image (AutoUpgrade) | Renamed file | +| --- | --- | +| `db_goldimage_19_32_.zip` (19.32) | `db_home_19.32.zip` | +| `db_goldimage_23_26_3_.zip` (23.26.3) | `db_home_26.03.zip` | + +A symlink with the original filename is created for the renamed file. +AutoUpgrade finds the file under the original name and skips a new download. +The symlinks can be removed for cleanup. They are not created again. + +Release and filename are taken from `patches_info.json` in `autoupgrade_download_dir`. +An existing file with the new name is never replaced. + +#### Default value + +```YAML +autoupgrade_download_gold_image_rename: false +``` + ### autoupgrade_download_latest Download the latest `autoupgrade.jar` from `autoupgrade_jar_url` into the software -repository on the Ansible controller before the installation. +repository before the installation. -Target is `autoupgrade_jar_filesource` or `oracle_sw_source_local`/`autoupgrade_jar`. -The download is done once (`run_once`) on `localhost` without `become`. -Requires `is_sw_source_local: true`. +The target depends on the location of the installation media: + +| Installation media | Download to | +| --- | --- | +| `oracle_sw_copy: true` or `autoupgrade_run_local: true` | Ansible controller (`run_once`, no `become`): `autoupgrade_jar_filesource` or `oracle_sw_source_local`/`autoupgrade_jar`. Requires `is_sw_source_local: true`. | +| `oracle_sw_copy: false` | target host as `oracle_user`: `autoupgrade_jar_filesource` or `oracle_stage_remote`/`autoupgrade_jar`. The directory must exist and be writable for `oracle_user`. | Existing installations are only replaced with `autoupgrade_force_update: true`. @@ -155,35 +195,6 @@ Default platform for the download, when `platform` is not set in `autoupgrade_do autoupgrade_download_platform: LINUX.X64 ``` -### autoupgrade_download_run_local - -Execute the download of patches (`download_patches.yml`) on the Ansible controller. -This includes the keystore (`keystore.yml`) and the installation of AutoUpgrade -needed for the download. - -`true`: Tasks are delegated to `localhost` with `run_once` and without `become`. -`autoupgrade_local_home` is used instead of `autoupgrade_home`. - -`false`: The download is executed on the target host as `oracle_user`. - -All other task files (e.g. `install.yml`) are always executed on the target host. - -_Important_ - -With `true` the download is executed only once (`run_once`) with the variables -of the first host in the play (`oracle_sw_patches`, `db_homes_installed`, `db_homes_config`, -`oracle_install_version_gi`, `autoupgrade_download_patches`). -These variables must be the same for all hosts in the play - e.g. defined in `group_vars/all` -for the whole environment. -When they are defined per host, limit the playbook to one host (`--limit `) -or execute it for each host. - -#### Default value - -```YAML -autoupgrade_download_run_local: true -``` - ### autoupgrade_download_supported_releases Releases supported by AutoUpgrade for downloading patches. @@ -214,7 +225,7 @@ AutoUpgrade does not accept Release Updates by patch number. The keyword is deri The result is added to `autoupgrade_download_patches`. -See `autoupgrade_download_run_local` for multiple hosts in the play. +See `autoupgrade_run_local` for multiple hosts in the play. Only entries from `oracle_sw_patches` are used, where `filename` matches `autoupgrade_download_filename_regex` and the release from `version` is in `autoupgrade_download_supported_releases`. Others (e.g. APEX, cvupack) are ignored with a warning. @@ -393,7 +404,7 @@ autoupgrade_keystore_timeout: 300 ### autoupgrade_local_home Directory for `autoupgrade.jar` and the generated AutoUpgrade config files -on the Ansible controller (`autoupgrade_download_run_local: true`). +on the Ansible controller (`autoupgrade_run_local: true`). #### Default value @@ -403,7 +414,7 @@ autoupgrade_local_home: "{{ lookup('ansible.builtin.env', 'HOME') }}/autoupgrade ### autoupgrade_local_java_home -JAVA_HOME used for AutoUpgrade on the Ansible controller (`autoupgrade_download_run_local: true`). +JAVA_HOME used for AutoUpgrade on the Ansible controller (`autoupgrade_run_local: true`). `java` from `PATH` is used, when `autoupgrade_local_java_home` is empty. #### Default value @@ -425,6 +436,34 @@ autoupgrade_log_dir: >- }} ``` +### autoupgrade_run_local + +Execute AutoUpgrade on the Ansible controller instead of the target host. +The switch is valid for all task files (`install.yml`, `keystore.yml`, `download_patches.yml`). + +`true` (default): Tasks are delegated to `localhost` with `run_once` and without `become`. +`autoupgrade_local_home` and `autoupgrade_local_java_home` are used. +This is useful for downloading patches into the software repository on the Ansible controller. + +`false`: Tasks are executed on the target host as `oracle_user`, +e.g. for the installation of AutoUpgrade on database servers. + +_Important_ + +With `true` the tasks are executed only once (`run_once`) with the variables +of the first host in the play (`oracle_sw_patches`, `db_homes_installed`, `db_homes_config`, +`oracle_install_version_gi`, `autoupgrade_download_patches`). +These variables must be the same for all hosts in the play - e.g. defined in `group_vars/all` +for the whole environment. +When they are defined per host, limit the playbook to one host (`--limit `) +or execute it for each host. + +#### Default value + +```YAML +autoupgrade_run_local: true +``` + ## Discovered Tags **_always_** diff --git a/roles/autoupgrade/defaults/main.yml b/roles/autoupgrade/defaults/main.yml index f88d57ac8..aa3381482 100644 --- a/roles/autoupgrade/defaults/main.yml +++ b/roles/autoupgrade/defaults/main.yml @@ -1,19 +1,18 @@ --- -# @var autoupgrade_download_run_local:description: > -# Execute the download of patches (`download_patches.yml`) on the Ansible controller. -# This includes the keystore (`keystore.yml`) and the installation of AutoUpgrade -# needed for the download. +# @var autoupgrade_run_local:description: > +# Execute AutoUpgrade on the Ansible controller instead of the target host. +# The switch is valid for all task files (`install.yml`, `keystore.yml`, `download_patches.yml`). # -# `true`: Tasks are delegated to `localhost` with `run_once` and without `become`. -# `autoupgrade_local_home` is used instead of `autoupgrade_home`. +# `true` (default): Tasks are delegated to `localhost` with `run_once` and without `become`. +# `autoupgrade_local_home` and `autoupgrade_local_java_home` are used. +# This is useful for downloading patches into the software repository on the Ansible controller. # -# `false`: The download is executed on the target host as `oracle_user`. -# -# All other task files (e.g. `install.yml`) are always executed on the target host. +# `false`: Tasks are executed on the target host as `oracle_user`, +# e.g. for the installation of AutoUpgrade on database servers. # # _Important_ # -# With `true` the download is executed only once (`run_once`) with the variables +# With `true` the tasks are executed only once (`run_once`) with the variables # of the first host in the play (`oracle_sw_patches`, `db_homes_installed`, `db_homes_config`, # `oracle_install_version_gi`, `autoupgrade_download_patches`). # These variables must be the same for all hosts in the play - e.g. defined in `group_vars/all` @@ -21,7 +20,7 @@ # When they are defined per host, limit the playbook to one host (`--limit `) # or execute it for each host. # @end -autoupgrade_download_run_local: true +autoupgrade_run_local: true # @var autoupgrade_home:description: > # Directory for `autoupgrade.jar` and the generated AutoUpgrade config files @@ -31,7 +30,7 @@ autoupgrade_home: "{{ oracle_base }}/product/autoupgrade" # @var autoupgrade_local_home:description: > # Directory for `autoupgrade.jar` and the generated AutoUpgrade config files -# on the Ansible controller (`autoupgrade_download_run_local: true`). +# on the Ansible controller (`autoupgrade_run_local: true`). # @end autoupgrade_local_home: "{{ lookup('ansible.builtin.env', 'HOME') }}/autoupgrade" @@ -55,11 +54,14 @@ autoupgrade_jar: autoupgrade.jar # @var autoupgrade_download_latest:description: > # Download the latest `autoupgrade.jar` from `autoupgrade_jar_url` into the software -# repository on the Ansible controller before the installation. +# repository before the installation. +# +# The target depends on the location of the installation media: # -# Target is `autoupgrade_jar_filesource` or `oracle_sw_source_local`/`autoupgrade_jar`. -# The download is done once (`run_once`) on `localhost` without `become`. -# Requires `is_sw_source_local: true`. +# | Installation media | Download to | +# | --- | --- | +# | `oracle_sw_copy: true` or `autoupgrade_run_local: true` | Ansible controller (`run_once`, no `become`): `autoupgrade_jar_filesource` or `oracle_sw_source_local`/`autoupgrade_jar`. Requires `is_sw_source_local: true`. | +# | `oracle_sw_copy: false` | target host as `oracle_user`: `autoupgrade_jar_filesource` or `oracle_stage_remote`/`autoupgrade_jar`. The directory must exist and be writable for `oracle_user`. | # # Existing installations are only replaced with `autoupgrade_force_update: true`. # @end @@ -89,7 +91,7 @@ autoupgrade_force_update: false autoupgrade_java_home: "" # @var autoupgrade_local_java_home:description: > -# JAVA_HOME used for AutoUpgrade on the Ansible controller (`autoupgrade_download_run_local: true`). +# JAVA_HOME used for AutoUpgrade on the Ansible controller (`autoupgrade_run_local: true`). # `java` from `PATH` is used, when `autoupgrade_local_java_home` is empty. # @end autoupgrade_local_java_home: "" @@ -198,7 +200,7 @@ autoupgrade_download_patches: [] # # The result is added to `autoupgrade_download_patches`. # -# See `autoupgrade_download_run_local` for multiple hosts in the play. +# See `autoupgrade_run_local` for multiple hosts in the play. # Only entries from `oracle_sw_patches` are used, where `filename` matches # `autoupgrade_download_filename_regex` and the release from `version` is in # `autoupgrade_download_supported_releases`. Others (e.g. APEX, cvupack) are ignored with a warning. @@ -237,3 +239,28 @@ autoupgrade_download_platform: LINUX.X64 # autoupgrade_download_gold_image: "NO" # @end autoupgrade_download_gold_image: "" + +# @var autoupgrade_download_gold_image_rename:description: > +# Rename downloaded Gold Images after the download. +# +# AutoUpgrade creates unique filenames with a timestamp, e.g. `db_goldimage_19_32_20261021112350.zip`. +# The file is renamed to `autoupgrade_download_gold_image_prefix` + release + `.zip`: +# +# | Gold Image (AutoUpgrade) | Renamed file | +# | --- | --- | +# | `db_goldimage_19_32_.zip` (19.32) | `db_home_19.32.zip` | +# | `db_goldimage_23_26_3_.zip` (23.26.3) | `db_home_26.03.zip` | +# +# A symlink with the original filename is created for the renamed file. +# AutoUpgrade finds the file under the original name and skips a new download. +# The symlinks can be removed for cleanup. They are not created again. +# +# Release and filename are taken from `patches_info.json` in `autoupgrade_download_dir`. +# An existing file with the new name is never replaced. +# @end +autoupgrade_download_gold_image_rename: false + +# @var autoupgrade_download_gold_image_prefix:description: > +# Prefix for the new filename of a Gold Image (`autoupgrade_download_gold_image_rename: true`). +# @end +autoupgrade_download_gold_image_prefix: db_home_ diff --git a/roles/autoupgrade/tasks/assert.yml b/roles/autoupgrade/tasks/assert.yml index 188cb6939..2ee58fa3a 100644 --- a/roles/autoupgrade/tasks/assert.yml +++ b/roles/autoupgrade/tasks/assert.yml @@ -22,8 +22,8 @@ label: "{{ aup.target_version | default('') }}: {{ aup.patch | default('') }}" # The target host must be prepared by ansible-oracle (playbook os / role orahost). -# autoupgrade does not create users or oracle_base. -- name: autoupgrade | Check oracle_user and oracle_base on target host +# autoupgrade does not create users. oracle_base is created in install.yml. +- name: autoupgrade | Check oracle_user on target host when: - not _autoupgrade_run_local | bool block: @@ -33,19 +33,13 @@ key: "{{ oracle_user }}" fail_key: false - - name: autoupgrade | Check oracle_base - ansible.builtin.stat: - path: "{{ oracle_base }}" - register: _autoupgrade_oracle_base_stat - - - name: autoupgrade | Assert oracle_user and oracle_base + - name: autoupgrade | Assert oracle_user ansible.builtin.assert: quiet: true that: - ansible_facts.getent_passwd[oracle_user] is not none - - _autoupgrade_oracle_base_stat.stat.isdir | default(false) fail_msg: >- - oracle_user '{{ oracle_user }}' or oracle_base '{{ oracle_base }}' missing on {{ inventory_hostname }}. + oracle_user '{{ oracle_user }}' missing on {{ inventory_hostname }}. Prepare the host with playbook opitzconsulting.ansible_oracle.os (role orahost) first. - name: autoupgrade | Check Java @@ -65,7 +59,7 @@ - _autoupgrade_java_res.rc == 0 fail_msg: >- '{{ _autoupgrade_java }}' is not executable on - {{ _autoupgrade_run_local | bool | ternary('Ansible controller (autoupgrade_download_run_local: true)', inventory_hostname) }}. + {{ _autoupgrade_run_local | bool | ternary('Ansible controller (autoupgrade_run_local: true)', inventory_hostname) }}. Set {{ _autoupgrade_run_local | bool | ternary('autoupgrade_local_java_home', 'autoupgrade_java_home') }} or install Java. {{ _autoupgrade_java_res.msg | default(_autoupgrade_java_res.stderr | default('')) }} diff --git a/roles/autoupgrade/tasks/download_patches.yml b/roles/autoupgrade/tasks/download_patches.yml index 6a408b0e3..a602f0a51 100644 --- a/roles/autoupgrade/tasks/download_patches.yml +++ b/roles/autoupgrade/tasks/download_patches.yml @@ -1,13 +1,9 @@ --- - name: autoupgrade | Install AutoUpgrade ansible.builtin.include_tasks: install.yml - vars: - _autoupgrade_run_local: "{{ autoupgrade_download_run_local | bool }}" - name: autoupgrade | Manage keystore ansible.builtin.include_tasks: keystore.yml - vars: - _autoupgrade_run_local: "{{ autoupgrade_download_run_local | bool }}" when: - autoupgrade_keystore_manage | bool @@ -17,7 +13,6 @@ delegate_to: "{{ _autoupgrade_delegate_to }}" run_once: "{{ _autoupgrade_run_local | bool }}" vars: - _autoupgrade_run_local: "{{ autoupgrade_download_run_local | bool }}" _autoupgrade_download_cfg: "{{ _autoupgrade_cfg_dir }}/download_patches.cfg" block: - name: autoupgrade | Assert patch list for download @@ -95,6 +90,67 @@ | reject('match', '^\s*$') | list }} + # Gold Images get unique filenames with a timestamp from AutoUpgrade. + # Rename them and create a symlink with the original filename, + # because AutoUpgrade skips the download when the file exists. + # Symlinks are created only after the rename => removed symlinks are not recreated. + - name: autoupgrade | Rename Gold Images + when: + - autoupgrade_download_gold_image_rename | bool + block: + - name: autoupgrade | Read patches_info.json + ansible.builtin.slurp: + src: "{{ autoupgrade_download_dir }}/patches_info.json" + register: _autoupgrade_patches_info + + - name: autoupgrade | Check downloaded Gold Images + ansible.builtin.stat: + path: "{{ autoupgrade_download_dir }}/{{ augi.src }}" + get_checksum: false + loop: "{{ _autoupgrade_gold_images }}" + loop_control: + loop_var: augi + label: "{{ augi.src }}" + register: _autoupgrade_gold_images_stat + + # creates: an existing file with the new name is never replaced + - name: autoupgrade | Rename Gold Image + ansible.builtin.command: + argv: + - mv + - "{{ autoupgrade_download_dir }}/{{ augs.augi.src }}" + - "{{ autoupgrade_download_dir }}/{{ augs.augi.dest }}" + creates: "{{ autoupgrade_download_dir }}/{{ augs.augi.dest }}" + loop: "{{ _autoupgrade_gold_images_stat.results }}" + loop_control: + loop_var: augs + label: "{{ augs.augi.src }} => {{ augs.augi.dest }}" + register: _autoupgrade_gold_images_mv + when: + # regular file only, not a symlink from a previous rename + - augs.stat.isreg | default(false) + + - name: autoupgrade | Create symlink with the original filename + ansible.builtin.file: + src: "{{ augm.augs.augi.dest }}" + dest: "{{ autoupgrade_download_dir }}/{{ augm.augs.augi.src }}" + state: link + loop: "{{ _autoupgrade_gold_images_mv.results | selectattr('changed') | list }}" + loop_control: + loop_var: augm + label: "{{ augm.augs.augi.src }} -> {{ augm.augs.augi.dest }}" + + - name: autoupgrade | Warn about Gold Images not renamed + ansible.builtin.debug: + msg: >- + Not renamed, because the file exists already: + {{ _autoupgrade_gold_images_mv.results + | rejectattr('skip_reason', 'defined') | rejectattr('changed') + | map(attribute='augs.augi.src') | list }} + when: + - _autoupgrade_gold_images_mv.results + | rejectattr('skip_reason', 'defined') | rejectattr('changed') | list | length > 0 + - name: autoupgrade | Warn about unavailable patches ansible.builtin.debug: msg: >- diff --git a/roles/autoupgrade/tasks/install.yml b/roles/autoupgrade/tasks/install.yml index 4667088d3..6ea2f0a31 100644 --- a/roles/autoupgrade/tasks/install.yml +++ b/roles/autoupgrade/tasks/install.yml @@ -1,16 +1,67 @@ --- +# The keystore console is controlled with ansible.builtin.expect, which needs the Python module pexpect +# on the host executing AutoUpgrade. pexpect is not installed by the role (package names differ between +# distributions) => check it with a dummy command for a clean error message. +- name: autoupgrade | Check Python module pexpect + ansible.builtin.expect: + command: "true" + responses: + "unused": "unused" + become: "{{ _autoupgrade_become }}" + become_user: "{{ oracle_user }}" + delegate_to: "{{ _autoupgrade_delegate_to }}" + run_once: "{{ _autoupgrade_run_local | bool }}" + register: _autoupgrade_pexpect_res + changed_when: false + failed_when: false + +- name: autoupgrade | Assert Python module pexpect + ansible.builtin.assert: + quiet: true + that: + - _autoupgrade_pexpect_res.rc | default(1) == 0 + fail_msg: >- + Python module pexpect is missing for the Python interpreter on + {{ _autoupgrade_run_local | bool | ternary('the Ansible controller', inventory_hostname) }}. + Install it (e.g. package python3-pexpect or pip install pexpect) and try again. + {{ _autoupgrade_pexpect_res.msg | default('') }} + - name: autoupgrade | Assert ansible.builtin.include_tasks: assert.yml tags: - assert - always -- name: autoupgrade | Download latest version into software repository +# AutoUpgrade can be used before the installation of the Oracle software +# (e.g. downloading patches for the installation) => oracle_base does not exist yet. +# Create it with the same attributes as oraswdb_install. The directories below are created as oracle_user. +- name: autoupgrade | Create oracle_base + ansible.builtin.file: + path: "{{ aub }}" + owner: "{{ oracle_user }}" + group: "{{ oracle_group }}" + mode: "0775" + state: directory + loop: + - "{{ oracle_base }}" + - "{{ oracle_base }}/cfgtoollogs" + loop_control: + loop_var: aub + become: true + when: + - not _autoupgrade_run_local | bool + +# Download the latest autoupgrade.jar into the software repository: +# - on the Ansible controller, when the installation media are copied from there +# (oracle_sw_copy: true) or AutoUpgrade is executed there (download_patches.yml) +# - on the target host, when the installation media are read from there (oracle_sw_copy: false) +- name: autoupgrade | Download latest version into software repository on Ansible controller become: false delegate_to: localhost run_once: true when: - autoupgrade_download_latest | bool + - oracle_sw_copy or _autoupgrade_run_local | bool block: - name: autoupgrade | Assert software repository is local ansible.builtin.assert: @@ -20,7 +71,7 @@ fail_msg: >- autoupgrade_download_latest requires is_sw_source_local: true - - name: autoupgrade | Download latest from {{ autoupgrade_jar_url }} + - name: autoupgrade | Download latest on Ansible controller from {{ autoupgrade_jar_url }} ansible.builtin.get_url: url: "{{ autoupgrade_jar_url }}" dest: "{{ _autoupgrade_jar_source_local }}" @@ -29,6 +80,23 @@ force: true environment: "{{ proxy_env }}" +- name: autoupgrade | Download latest on target host from {{ autoupgrade_jar_url }} + ansible.builtin.get_url: + url: "{{ autoupgrade_jar_url }}" + dest: "{{ _autoupgrade_jar_source_remote }}" + mode: "0644" + # always check for a newer file. changed only when file differs + force: true + client_cert: "{{ get_url_ssl_client_cert | default(omit) }}" + client_key: "{{ get_url_ssl_client_key | default(omit) }}" + environment: "{{ proxy_env }}" + become: true + become_user: "{{ oracle_user }}" + when: + - autoupgrade_download_latest | bool + - not oracle_sw_copy + - not _autoupgrade_run_local | bool + - name: autoupgrade | Install become: "{{ _autoupgrade_become }}" become_user: "{{ oracle_user }}" @@ -73,7 +141,7 @@ - name: autoupgrade | Copy from remote stage {{ autoupgrade_jar }} ansible.builtin.copy: - src: "{{ autoupgrade_jar_filesource | default(oracle_stage_remote + '/' + autoupgrade_jar, true) }}" + src: "{{ _autoupgrade_jar_source_remote }}" dest: "{{ _autoupgrade_jar_path }}" mode: "0644" force: "{{ autoupgrade_force_update }}" diff --git a/roles/autoupgrade/vars/main.yml b/roles/autoupgrade/vars/main.yml index b2bd747f8..577cbb17d 100644 --- a/roles/autoupgrade/vars/main.yml +++ b/roles/autoupgrade/vars/main.yml @@ -1,8 +1,6 @@ --- -# Execution on the Ansible controller (delegate_to localhost, run_once, no become). -# Only download_patches.yml sets it to autoupgrade_download_run_local for itself -# and for the included install.yml / keystore.yml (task vars override role vars). -_autoupgrade_run_local: false +# Execution on the Ansible controller (delegate_to localhost, run_once, no become) +_autoupgrade_run_local: "{{ autoupgrade_run_local | bool }}" _autoupgrade_home: >- {{ _autoupgrade_run_local | bool | ternary(autoupgrade_local_home, autoupgrade_home) }} @@ -13,6 +11,10 @@ _autoupgrade_jar_path: "{{ _autoupgrade_home }}/{{ autoupgrade_jar }}" _autoupgrade_jar_source_local: >- {{ autoupgrade_jar_filesource | default(oracle_sw_source_local + '/' + autoupgrade_jar, true) }} +# autoupgrade.jar in software repository on the target host (oracle_sw_copy: false) +_autoupgrade_jar_source_remote: >- + {{ autoupgrade_jar_filesource | default(oracle_stage_remote + '/' + autoupgrade_jar, true) }} + _autoupgrade_cfg_dir: "{{ _autoupgrade_home }}/cfg" # SHA256 of mos_password, when autoupgrade_keystore_password is empty @@ -114,3 +116,25 @@ _autoupgrade_download_list: >- # expected files from oracle_sw_patches after download _autoupgrade_download_expected: >- {{ _autoupgrade_download_sw_patches | map(attribute='filename') | unique | list }} + +# Gold Images from patches_info.json (autoupgrade_download_gold_image_rename) +# src: filename created by AutoUpgrade, e.g. db_goldimage_19_32_20261021112350.zip +# dest: autoupgrade_download_gold_image_prefix + release + .zip +# 19.32.0.0.0 => 19.32, 23.26.3.0.0 => 26.03 (23ai with RU >= 23.26) +_autoupgrade_gold_images: >- + {%- set ns = namespace(res=[]) -%} + {%- set info = (_autoupgrade_patches_info.content | default('') | b64decode or '{}') | from_json -%} + {%- for p in info.patches | default([]) -%} + {%- if p.description | default('') is search('Gold Image') and p.releaseUpdate is defined -%} + {%- set v = (p.releaseUpdate | string).split('.') -%} + {%- if v[0] | int == 23 and v[1] | default(0) | int >= 26 -%} + {%- set rel = v[1] ~ '.' ~ ('%02d' | format(v[2] | default(0) | int)) -%} + {%- else -%} + {%- set rel = v[0] ~ '.' ~ v[1] | default('0') -%} + {%- endif -%} + {%- for f in p.files | default([]) -%} + {%- set ns.res = ns.res + [{'src': f.name, 'dest': autoupgrade_download_gold_image_prefix ~ rel ~ '.zip'}] -%} + {%- endfor -%} + {%- endif -%} + {%- endfor -%} + {{ ns.res }}