Merge "Support prestage N release --for-sw-deploy on subclouds N-1 without USM"

This commit is contained in:
Zuul 2024-11-28 23:13:14 +00:00 committed by Gerrit Code Review
commit 68afdb411f
7 changed files with 504 additions and 293 deletions

View File

@ -36,6 +36,7 @@
- name: Set prestage dir and subdirectory facts
set_fact:
prestage_source: remote
software_bin: "/usr/bin/software"
prestage_dir: "{{ platform_backup_dir }}/{{ software_version }}"
host_software_metadata_dir: "/opt/software/metadata"
patches_prestage_dir: "{{ platform_backup_dir }}/{{ software_version }}/patches"

View File

@ -52,18 +52,32 @@
set_fact:
host_patches_exist: "{{ host_patch_dir_result.stat.exists }}"
- name: Check if {{ software_bin }} exists on {{ inventory_hostname }}
stat:
path: "{{ software_bin }}"
register: software_bin_result
- name: Set flag to indicate usm is enabled in the host
set_fact:
usm_enabled_on_subcloud: "{{ software_bin_result.stat.exists }}"
# The subcloud_is_previous_release flag determines whether the subcloud release
# corresponds to an N-1 release.
- name: Set flag to indicate if subcloud prestage is for N-1 scenario
set_fact:
subcloud_is_previous_release: "{{ 'true' if (prestage_source == 'remote' and
host_software_version is version('22.12', '='))
else 'false' }}"
# The force_ostree_dir_sync flag determines whether the entire N release ostree
# directory should be copied to the subcloud or not. This flag is only relevant
# if the subcloud is running N-1 release.
# The condition for it to be true must meet:
# - The release of the subcloud must be different from the release being
# prestaged.
# - The release of the subcloud must be a N-1 release that is USM enabled.
# - The release of the subcloud must be an N-1 release (subcloud_is_previous_release)
# - The N release ostree directory does not already exist on the N-1 subcloud.
- name: Set flag to indicate if subcloud prestage is for N-1 scenario
- name: Set flag to indicate if the ostree directory should be copied to the subcloud
set_fact:
force_ostree_dir_sync: "{{ 'true' if (prestage_source == 'remote' and
host_software_version is version('22.12', '=') and
force_ostree_dir_sync: "{{ 'true' if (subcloud_is_previous_release and
not host_ostree_dir_exist) else 'false' }}"
- debug:
@ -72,5 +86,7 @@
Prestaging reason: {{ prestage_reason }}
Prestaging source: {{ prestage_source }}
Prestaging os type: {{ prestage_os_type }}
Prestaging for N-1 subcloud: {{ force_ostree_dir_sync }}
Prestaging for N-1 subcloud: {{ subcloud_is_previous_release }}
Force ostree dir sync for N-1 subcloud: {{ force_ostree_dir_sync }}
USM enabled on subcloud: {{ usm_enabled_on_subcloud }}
Release feed directory (on target): {{ release_feed|default('N/A') }}

View File

@ -38,9 +38,6 @@ SW_VERSION=${SW_VERSION:-}
DEBUG=${DEBUG:-}
DRY_RUN=${DRY_RUN:-}
USM_SOFTWARE_DIR=/opt/software
USM_METADATA_DIR=${USM_SOFTWARE_DIR}/metadata
help() {
cat<<EOF
ostree metadata synchronization utilities.
@ -151,8 +148,9 @@ initialize_env() {
log_warn "not found: /etc/platform/openrc"
fi
export METADATA_DIR=${METADATA_DIR:-/opt/software/metadata}
export METADATA_SYNC_DIR=${METADATA_SYNC_DIR:-/opt/software/tmp/metadata-sync}
export SOFTWARE_DIR=/opt/software
export METADATA_DIR=${METADATA_DIR:-${SOFTWARE_DIR}/metadata}
export METADATA_SYNC_DIR=${METADATA_SYNC_DIR:-${SOFTWARE_DIR}/tmp/metadata-sync}
export METADATA_SYNC_METADATA_DIR=${METADATA_SYNC_DIR}/metadata
# shellcheck disable=SC1091
@ -526,6 +524,11 @@ sync_metadata_on_subcloud() {
# Create it with STATE = available
new_state="available"
fi
# Ensures that the new state directory exists
if [ ! -d "${METADATA_DIR}/${new_state}" ]; then
log_info "Creating ${METADATA_DIR}/${new_state} state directory"
run_cmd mkdir -p "${METADATA_DIR}/${new_state}"
fi
log_info "${log_hdr} does not exist on subcloud, setting to ${new_state}"
run_cmd cp "${central_metadata_file}" "${METADATA_DIR}/${new_state}"
fi
@ -565,8 +568,8 @@ sync_subcloud_metadata() {
# Remove current files for specified release
log_info "Removing directories for release ${sw_version}"
rm -Rf ${USM_SOFTWARE_DIR}/rel-${sw_version}.*
find ${USM_METADATA_DIR} -type f -name "*${sw_version}*" | xargs rm -f
rm -Rf ${SOFTWARE_DIR}/rel-${sw_version}.*
find ${METADATA_DIR} -type f -name "*${sw_version}*" | xargs rm -f
# Get list of metadata files requiring sync
for metadata_file in $(get_metadata_files_unique_to_central); do

View File

@ -7,34 +7,29 @@
# ROLE DESCRIPTION:
#
# This role synchronizes the system controller /opt/software/metadata
# directory to the subcloud.
# directory and ostree repository to the subcloud.
#
# For the N-1 scenario we use the force_ostree_dir_sync variable to determine if it is
# necessary to copy the entire ostree repo directory from the system controller
# release.
# We can divide this playbook into three files and few common tasks
# that are necessary.
# The description of each file is detailed in each of them.
#
# Note: much of the work is done by the ostree-metadata-sync.sh script, which
# has two targets: get-commits and sync-subcloud
# Force ostree dir sync:
# Includes the file perform_full_ostree_dir_sync.yml that is executed when
# the flag force_ostree_dir_sync is set.
# This is to ensure the existence of the release N ostree directory in an
# N-1 subcloud.
#
# Procedure:
# - On system controller, run ostree-metadata-sync.sh --sw-version 24.09 get-commits
# - Creates /opt/software/tmp/metadata-sync/ostree-metadata-commits.central
# which contains list of sw_version:ostree commit for all
# software updates matching prestaging software release
# - this file is transferred to subcloud for use during the sync-subcloud stage
# - On subcloud, run ostree-metadata-sync.sh --sw-version 24.09 get-commits
# - Creates /opt/software/tmp/metadata-sync/ostree-metadata-commits.subcloud
# which contains list of sw_version:ostree commit for all software
# updates matching prestaging software release
# - As long as the patch level of the system controller is higher than that of the subcloud
# - Transfer the following from system controller to subcloud at /opt/software/tmp/metadata-sync:
# - /opt/software/tmp/metadata-sync/ostree-metadata-commits.central
# - the full /opt/software/metadata hierarchy
# - The above data is used on the subcloud to synchronize the commits on the subcloud
# by invoking: ostree-metadata-sync.sh --sw-version 24.09 sync-subcloud
# - operates on the data in /opt/software/tmp/metadata-sync
# plus the state on subcloud to run the sync algorithm for each commit
# - Otherwise, the prestage should not be executed.
# Sync patches to USM enabled subcloud:
# Includes the file sync_patches_to_usm_subcloud.yml that is executed when
# the flag usm_enabled_on_subcloud is set.
# This is to synchronize patch metadata and commits for an N or N-1 release.
#
# Sync patches to non USM enabled subcloud
# Includes the file sync_patches_to_non_usm_subcloud.yml that is executed when
# the flag usm_enabled_on_subcloud is not set.
# Having the ostree repository synchronized by role #1, now we need to transfer
# the patch metadata files and scripts directories only if host is a non-USM
# N-1 subcloud.
#
- name: Set software metadata synchronization facts for {{ software_version }}
@ -44,61 +39,19 @@
ostree_rev: starlingx
usm_software_dir: /opt/software
usm_metadata_dir: /opt/software/metadata
usm_software_scripts_dir: /opt/software/software-scripts
tmp_metadata_sync_dir: /opt/software/tmp/metadata-sync
ostree_metadata_commits_central: /opt/software/tmp/metadata-sync/ostree-metadata-commits.central
ostree_metadata_commits_subcloud: /opt/software/tmp/metadata-sync/ostree-metadata-commits.subcloud
- block:
# Transfer the ostree directory from the system controller to the subcloud
# in case the scenario corresponds to initial N-1.
# Once the directory is copied (or exists) in the subcloud, this block will
# no longer be executed.
# It's necessary to temporarily change the owner to sysadmin so that
# the system controller can push the files to the subcloud, since the files
# are in the folders only the root can access but the synchronize only
# support passwordless sysadmin to execute ssh and rsync.
- name: Temporarily change the ownership of feed directory {{ release_feed }}
file:
path: "{{ release_feed }}"
state: directory
owner: sysadmin
recurse: yes
- name: Copy feed directory from system controller to subcloud
synchronize:
mode: push
src: "{{ release_feed }}/"
dest: "{{ release_feed }}/"
rsync_opts: "--delete"
register: prestage_transfer
retries: 3
delay: 5
until: prestage_transfer.rc == 0
- name: Check if install_uuid file exists in {{ host_software_version }} feed directory
stat:
path: "{{ release_feed | dirname }}/rel-{{ host_software_version }}/install_uuid"
register: install_uuid_exists
- name: Copy install_uuid file from {{ host_software_version }} to {{ software_version }} feed directory
copy:
src: "{{ release_feed | dirname }}/rel-{{ host_software_version }}/install_uuid"
dest: "{{ release_feed }}/install_uuid"
force: true
remote_src: yes
when: install_uuid_exists.stat.exists
always:
- name: Restore the ownership of the feed directory {{ release_feed }}
file:
path: "{{ release_feed }}"
state: directory
owner: root
recurse: yes
become: true
- name: Force ostree dir sync
include_tasks: perform_full_ostree_dir_sync.yml
when: force_ostree_dir_sync
# These tasks are common to use in the following tasks:
# Sync patches to USM enabled subcloud
# Sync patches to non USM enabled subcloud
#
- name: Gather system controller ostree commit
command: ostree --repo={{ ostree_repo_release_feed }} rev-parse {{ ostree_rev }}
register: ostree_commit_system_controller
@ -112,220 +65,21 @@
shell: software list --release {{ software_version }} --state deployed | \
grep {{ software_version }} | sed 's/ //g;'
register: system_controller_software_list
failed_when: false
delegate_to: localhost
- name: Show system controller deployed software list for release {{ software_version }}
debug:
var: system_controller_software_list.stdout
- name: Gather subcloud deployed software list
shell: software list --release {{ software_version }} --state deployed | \
grep {{ software_version }} | sed 's/ //g;'
register: subcloud_software_list
failed_when: false
become: true
- name: Show subcloud deployed software list for release {{ software_version }}
debug:
var: subcloud_software_list.stdout
- name: Ensure system controller {{ tmp_metadata_sync_dir }} exists (sysadmin)
file:
path: "{{ tmp_metadata_sync_dir }}"
owner: sysadmin
group: root
state: directory
mode: 0755
recurse: yes
become: true
delegate_to: localhost
- name: Ensure subcloud {{ tmp_metadata_sync_dir }} exists (sysadmin)
file:
path: "{{ tmp_metadata_sync_dir }}"
owner: sysadmin
group: root
state: directory
mode: 0755
recurse: yes
become: true
- name: Extract release part from system controller release list
set_fact:
system_controller_releases: "{{ system_controller_software_list.stdout_lines | \
map('regex_replace', '.*?-([0-9\\.]+).*', '\\1') | list }}"
- name: Extract release part from subcloud release list
set_fact:
subcloud_releases: "{{ subcloud_software_list.stdout_lines | \
map('regex_replace', '.*?-([0-9\\.]+).*', '\\1') | list }}"
- name: Sync patches to USM enabled subcloud
include_tasks: sync_patches_to_usm_subcloud.yml
when: usm_enabled_on_subcloud
# The subcloud must have at least one release for the given software version to be able
# to compare with the system controller version. Otherwise, it is assumed that the
# release does not exist in the subcloud and the prestage is executed.
- block:
# It is necessary to compare the current patch level between the SC and the subcloud
# to determine if prestage should be executed. In this way all scenarios are covered,
# including pre-patched scenario.
- name: Extract current patch number from system controller release list
set_fact:
system_controller_current_patch: "{{ system_controller_releases[-1] | \
regex_replace('.*\\.', '') | int }}"
- name: Extract current patch number from subcloud release list
set_fact:
subcloud_current_patch: "{{ subcloud_releases[-1] | regex_replace('.*\\.', '') | int }}"
# We need to compare the patch level, since we must take into account even the
# pre-patched scenario.
- debug:
msg: |
ostree revision from: {{ ostree_repo_release_feed }}:
system controller current patch: {{ system_controller_releases[-1] }}
subcloud current patch: {{ subcloud_releases[-1] }}
system controller current commit: {{ ostree_commit_system_controller.stdout }}
subcloud current commit: {{ ostree_commit_subcloud.stdout }}
{% if system_controller_current_patch == subcloud_current_patch %}
Skipping for software deploy prestage as the subcloud has the same patch level
than the system controller.
{% elif subcloud_current_patch > system_controller_current_patch %}
Skipping for software deploy prestage as the subcloud has a higher patch level
than the system controller.
{% endif %}
- name: "Subcloud does not require software prestage. Exiting..."
meta: end_play
when: subcloud_current_patch >= system_controller_current_patch
when: subcloud_releases | length > 0
- block:
- debug:
msg: The system controller has a patch level higher than the subcloud
- name: Gather system controller metadata commits
#
# Use the existing ostree_metadata_commits_central file if:
# 1) It exists, and
# 2) There are no new commits. Compare last line of the ostree_metadata_commits_central
# file against current ostree repo commit.
# Otherwise, we generate a new ostree_metadata_commits_central file using the
# get-commits target to our script.
#
# Get the commits from the metadata, in the same way that software list does,
# avoiding ambiguous queries.
# Parallel operations (for orchestration):
# We use flock here because there may be many prestaging operations running
# in parallel on system controller. flock behaviour:
# - acquire lock on /tmp/ostree_metadata_commits_central.lock
# - the timeout is long just to ensure we never deadlock for any reason
shell: |
exec 3>/tmp/ostree_metadata_commits_central.lock
flock --exclusive --timeout 180 3 || \
{ echo "ERROR: $? - flock failed while trying to get the commits."; exit 1; }
if [ ! -f "{{ ostree_metadata_commits_central }}" ] \
|| ! diff -q <(echo {{ ostree_commit_system_controller.stdout }}) \
<(tail --lines=1 "{{ ostree_metadata_commits_central }}" | awk -F':' '{ print $2; }') > \
/dev/null 2>&1 ; then
{{ role_path }}/files/ostree-metadata-sync.sh --sw-version "{{ software_version }}" \
--output "{{ ostree_metadata_commits_central }}" get-commits
else
cat "{{ ostree_metadata_commits_central }}"
fi
exec 3>&- # release the lock
register: system_controller_software_metadata_commits
delegate_to: localhost
- name: Show ostree metadata commits on system controller
debug:
var: system_controller_software_metadata_commits
# Switch from command to script module to run the ostree-metadata-sync.sh script
# on the system controller as it does not exist on N-1 release e.g. 22.12
- name: Gather subcloud metadata commits
script: "{{ role_path }}/files/ostree-metadata-sync.sh --sw-version {{ software_version }}
--output {{ ostree_metadata_commits_subcloud }} get-commits"
register: subcloud_software_metadata_commits
- name: Show ostree metadata commits on subcloud
debug:
var: subcloud_software_metadata_commits
- block:
# It's necessary to temporarily change the owner to sysadmin so that
# the system controller can push the files to the subcloud, since the files
# are in the folders only the root can access but the synchronize only
# support passwordless sysadmin to execute ssh and rsync.
- name: Temporarily change the ownership of {{ usm_software_dir }}
file:
path: "{{ usm_software_dir }}"
state: directory
owner: sysadmin
recurse: yes
- name: Copy system controller {{ usm_metadata_dir }} to subcloud {{ tmp_metadata_sync_dir }}
copy:
src: "{{ usm_metadata_dir }}"
dest: "{{ tmp_metadata_sync_dir }}"
force: true
- name: Copy system controller {{ ostree_metadata_commits_central }} to subcloud {{ tmp_metadata_sync_dir }}
copy:
src: "{{ ostree_metadata_commits_central }}"
dest: "{{ tmp_metadata_sync_dir }}"
force: true
# Switch from command to script module to run the ostree-metadata-sync.sh script
# on the system controller as it does not exist on N-1 release e.g. 22.12
- name: Synchronizing system controller ostree commits on subcloud
script: "{{ role_path }}/files/ostree-metadata-sync.sh --sw-version {{ software_version }}
sync-subcloud"
register: sync_software_commits
become: true
- name: Show sync output
debug:
msg:
- "sync_software_commits:"
- "rc: {{ sync_software_commits.rc }}"
- "stderr: {{ sync_software_commits.stderr }}"
- "stdout: {{ sync_software_commits.stdout }}"
- name: Copy system controller deployed release directory to subcloud
synchronize:
mode: "push"
src: "{{ usm_software_dir }}/rel-{{ item }}"
dest: "{{ usm_software_dir }}"
with_items: "{{ system_controller_releases }}"
failed_when: false
- name: Copy system controller {{ usm_software_dir }}/software-scripts to subcloud
synchronize:
mode: "push"
src: "{{ usm_software_dir }}/software-scripts"
dest: "{{ usm_software_dir }}"
failed_when: false
always:
- block:
- name: Restore the ownership of {{ usm_software_dir }}
file:
path: "{{ usm_software_dir }}"
state: directory
owner: root
recurse: yes
- name: Restore the ownership of {{ tmp_metadata_sync_dir }}
file:
path: "{{ tmp_metadata_sync_dir }}"
state: directory
owner: sysadmin
recurse: yes
- name: Synchronize software between controllers
command: "{{ usm_scripts_dir }}/controllers-software-sync"
- name: Synchronize {{ release_feed }} directory between controllers
command: "{{ usm_scripts_dir }}/sync-controllers-feed --feed={{ release_feed }}"
become: true
- name: Sync patches to non USM enabled subcloud
include_tasks: sync_patches_to_non_usm_subcloud.yml
when: not usm_enabled_on_subcloud

View File

@ -0,0 +1,63 @@
---
#
# Copyright (c) 2024 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
# ROLE DESCRIPTION:
#
# This role is only executed when the subcloud has an N-1 release, where the
# ostree repository for N release will be transferred entirely to prepare
# the subcloud. It is executed at least once as long as the release N ostree
# directory does not exist in the subcloud and if the subcloud is N-1.
# Once the ostree N directory was transferred, if the playbook were to be
# executed again, the file will not be executed.
# The force_ostree_dir_sync variable must be set to true in order to execute
# this role.
#
- name: Perform full ostree repo sync
block:
# It's necessary to temporarily change the owner to sysadmin so that
# the system controller can push the files to the subcloud, since the files
# are in the folders only the root can access but the synchronize only
# support passwordless sysadmin to execute ssh and rsync.
- name: Temporarily change the ownership of feed directory {{ release_feed }}
file:
path: "{{ release_feed }}"
state: directory
owner: sysadmin
recurse: yes
- name: Copy feed directory from system controller to subcloud
synchronize:
mode: push
src: "{{ release_feed }}/"
dest: "{{ release_feed }}/"
rsync_opts: "--delete"
register: prestage_transfer
retries: 3
delay: 5
until: prestage_transfer.rc == 0
- name: Check if install_uuid file exists in {{ host_software_version }} feed directory
stat:
path: "{{ release_feed | dirname }}/rel-{{ host_software_version }}/install_uuid"
register: install_uuid_exists
- name: Copy install_uuid file from {{ host_software_version }} to {{ software_version }} feed directory
copy:
src: "{{ release_feed | dirname }}/rel-{{ host_software_version }}/install_uuid"
dest: "{{ release_feed }}/install_uuid"
force: true
remote_src: yes
when: install_uuid_exists.stat.exists
always:
- name: Restore the ownership of the feed directory {{ release_feed }}
file:
path: "{{ release_feed }}"
state: directory
owner: root
recurse: yes
become: true

View File

@ -0,0 +1,106 @@
---
#
# Copyright (c) 2024 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
# ROLE DESCRIPTION:
#
# This role is executed when there is no USM support, generally in subclouds that
# have release N-1 but without USM support.
# It is commonly executed after perform_full_ostree_dir_sync role, since
# both share the N-1 configuration.
# It is adapted to be able to carry out the upgrade from release N-1 without USM
# support to release N, prestaging release N files to the subcloud.
# The upgrade to release N cannot be carried out until the patch with USM support
# is deployed in the subcloud. Once the patch with USM support is installed, the
# deploy can be executed with the prestaged data.
# The usm_enabled_on_subcloud variable must be set to false in order to execute
# this role.
#
- name: Perform sync patches to non USM subcloud
block:
- debug:
msg: The subcloud has N-1 release without USM support. Prestaging release {{ software_version }}
# It's necessary to temporarily change the owner to sysadmin so that
# the system controller can push the files to the subcloud, since the files
# are in the folders only the root can access but the synchronize only
# support passwordless sysadmin to execute ssh and rsync.
- name: Temporarily change the ownership of {{ usm_software_dir }}
file:
path: "{{ usm_software_dir }}"
state: directory
owner: sysadmin
recurse: yes
- name: Ensure subcloud {{ usm_metadata_dir }}/available exists (sysadmin)
file:
path: "{{ usm_metadata_dir }}/available"
owner: sysadmin
group: root
state: directory
mode: 0755
recurse: yes
- name: Find deployed metadata files on system controller
command: find {{ usm_metadata_dir }} -type f -name "*{{ software_version }}*"
register: system_controller_metadata_files
delegate_to: localhost
- name: Copy system controller deployed metadata files as available state to subcloud
copy:
src: "{{ item }}"
dest: "{{ usm_metadata_dir }}/available/{{ item | basename }}"
with_items: "{{ system_controller_metadata_files.stdout_lines }}"
# We want to transfer the rel-MM-mm directories that may exist in the system
# controller to the subcloud. There will always be at least one, which corresponds
# to the deployed base release, for example rel-24.09.0. This task should not fail,
# if it fails the playbook should be aborted.
- name: Copy system controller deployed release directory to subcloud
synchronize:
mode: "push"
src: "{{ usm_software_dir }}/rel-{{ item }}"
dest: "{{ usm_software_dir }}/"
rsync_opts: "--delete"
with_items: "{{ system_controller_releases }}"
register: releases_transfer
retries: 3
delay: 2
until: releases_transfer.rc == 0
# We want to check if the software-script directory exists on the system controller
# to ensure copying to the subcloud. This directory is created when a new patch is
# deployed, so it does not exist if only the base release is deployed, for example
# 24.09.0.
- name: Check if {{ usm_software_scripts_dir }} directory exists
stat:
path: "{{ usm_software_scripts_dir }}"
register: software_scripts_exists
delegate_to: localhost
# Only if the directory exists, it will be transferred to the subcloud.
# We cannot deploy a patch if the directory does not exist, therefore the playbook
# must abort if the transfer fails.
- name: Copy system controller {{ usm_software_scripts_dir }} to subcloud
synchronize:
mode: "push"
src: "{{ usm_software_scripts_dir }}"
dest: "{{ usm_software_dir }}/"
rsync_opts: "--delete"
register: scripts_transfer
retries: 3
delay: 2
until: scripts_transfer.rc == 0
when: software_scripts_exists.stat.exists
always:
- name: Restore the ownership of {{ usm_software_dir }}
file:
path: "{{ usm_software_dir }}"
state: directory
owner: root
recurse: yes
become: true

View File

@ -0,0 +1,268 @@
---
#
# Copyright (c) 2024 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
# ROLE DESCRIPTION:
#
# This role is executed only if USM is supported, both in an N and an N-1 release.
# It compares the releases from the software utility and determines if the system
# controller has a patch level higher than that of the subcloud. If that happens,
# the patch deployed on the system controller will be prestaged incrementally
# to the subcloud. The usm_enabled_on_subcloud variable must be set to true in
# order to execute this role
#
# Note: Much of the work is done by the ostree-metadata-sync.sh script, which has
# two targets: get-commits and sync-subcloud.
#
# Procedure:
# - On system controller, run ostree-metadata-sync.sh --sw-version 24.09 get-commits
# - Creates /opt/software/tmp/metadata-sync/ostree-metadata-commits.central
# which contains list of sw_version:ostree commit for all
# software updates matching prestaging software release
# - this file is transferred to subcloud for use during the sync-subcloud stage
# - On subcloud, run ostree-metadata-sync.sh --sw-version 24.09 get-commits
# - Creates /opt/software/tmp/metadata-sync/ostree-metadata-commits.subcloud
# which contains list of sw_version:ostree commit for all software
# updates matching prestaging software release
# - As long as the patch level of the system controller is higher than that of the subcloud
# - Transfer the following from system controller to subcloud at
# /opt/software/tmp/metadata-sync:
# - /opt/software/tmp/metadata-sync/ostree-metadata-commits.central
# - the full /opt/software/metadata hierarchy
# - The above data is used on the subcloud to synchronize the commits on the subcloud
# by invoking: ostree-metadata-sync.sh --sw-version 24.09 sync-subcloud
# - operates on the data in /opt/software/tmp/metadata-sync
# plus the state on subcloud to run the sync algorithm for each commit
# - Otherwise, the prestage should not be executed.
#
- name: Perform sync patches to USM subcloud
# This block is executed for subcloud N and even N-1 scenario with USM support.
block:
- name: Gather subcloud deployed software list
shell: software list --release {{ software_version }} --state deployed | \
grep {{ software_version }} | sed 's/ //g;'
register: subcloud_software_list
- name: Show subcloud deployed software list for release {{ software_version }}
debug:
var: subcloud_software_list.stdout
- name: Ensure system controller {{ tmp_metadata_sync_dir }} exists (sysadmin)
file:
path: "{{ tmp_metadata_sync_dir }}"
owner: sysadmin
group: root
state: directory
mode: 0755
recurse: yes
delegate_to: localhost
- name: Ensure subcloud {{ tmp_metadata_sync_dir }} exists (sysadmin)
file:
path: "{{ tmp_metadata_sync_dir }}"
owner: sysadmin
group: root
state: directory
mode: 0755
recurse: yes
- name: Extract release part from subcloud release list
set_fact:
subcloud_releases: "{{ subcloud_software_list.stdout_lines | \
map('regex_replace', '.*?-([0-9\\.]+).*', '\\1') | list }}"
# The subcloud must have at least one release for the given software version to be able
# to compare with the system controller version. Otherwise, it is assumed that the
# release does not exist in the subcloud and the prestage is executed.
- block:
# It is necessary to compare the current patch level between the SC and the subcloud
# to determine if prestage should be executed. In this way all scenarios are covered,
# including pre-patched scenario.
- name: Extract current patch number from system controller release list
set_fact:
system_controller_current_patch: "{{ system_controller_releases[-1] | \
regex_replace('.*\\.', '') | int }}"
- name: Extract current patch number from subcloud release list
set_fact:
subcloud_current_patch: "{{ subcloud_releases[-1] | regex_replace('.*\\.', '') | int }}"
# We need to compare the patch level, since we must take into account even the
# pre-patched scenario.
- debug:
msg: |
ostree revision from: {{ ostree_repo_release_feed }}:
system controller current patch: {{ system_controller_releases[-1] }}
subcloud current patch: {{ subcloud_releases[-1] }}
system controller current commit: {{ ostree_commit_system_controller.stdout }}
subcloud current commit: {{ ostree_commit_subcloud.stdout }}
{% if system_controller_current_patch == subcloud_current_patch %}
Skipping for software deploy prestage as the subcloud has the same patch level
than the system controller.
{% elif subcloud_current_patch > system_controller_current_patch %}
Skipping for software deploy prestage as the subcloud has a higher patch level
than the system controller.
{% endif %}
- name: "Subcloud does not require software prestage. Exiting..."
meta: end_play
when: subcloud_current_patch >= system_controller_current_patch
become: true
when: subcloud_releases | length > 0
- block:
- debug:
msg: The system controller has a patch level higher than the subcloud
- name: Gather system controller metadata commits
#
# Use the existing ostree_metadata_commits_central file if:
# 1) It exists, and
# 2) There are no new commits. Compare last line of the ostree_metadata_commits_central
# file against current ostree repo commit.
# Otherwise, we generate a new ostree_metadata_commits_central file using the
# get-commits target to our script.
#
# Get the commits from the metadata, in the same way that software list does,
# avoiding ambiguous queries.
# Parallel operations (for orchestration):
# We use flock here because there may be many prestaging operations running
# in parallel on system controller. flock behaviour:
# - acquire lock on /tmp/ostree_metadata_commits_central.lock
# - the timeout is long just to ensure we never deadlock for any reason
shell: |
exec 3>/tmp/ostree_metadata_commits_central.lock
flock --exclusive --timeout 180 3 || \
{ echo "ERROR: $? - flock failed while trying to get the commits."; exit 1; }
if [ ! -f "{{ ostree_metadata_commits_central }}" ] \
|| ! diff -q <(echo {{ ostree_commit_system_controller.stdout }}) \
<(tail --lines=1 "{{ ostree_metadata_commits_central }}" | awk -F':' '{ print $2; }') > \
/dev/null 2>&1 ; then
{{ role_path }}/files/ostree-metadata-sync.sh --sw-version "{{ software_version }}" \
--output "{{ ostree_metadata_commits_central }}" get-commits
else
cat "{{ ostree_metadata_commits_central }}"
fi
exec 3>&- # release the lock
register: system_controller_software_metadata_commits
delegate_to: localhost
- name: Show ostree metadata commits on system controller
debug:
var: system_controller_software_metadata_commits
# Switch from command to script module to run the ostree-metadata-sync.sh script
# on the system controller as it does not exist on N-1 release e.g. 22.12
- name: Gather subcloud metadata commits
script: "{{ role_path }}/files/ostree-metadata-sync.sh --sw-version {{ software_version }}
--output {{ ostree_metadata_commits_subcloud }} get-commits"
register: subcloud_software_metadata_commits
- name: Show ostree metadata commits on subcloud
debug:
var: subcloud_software_metadata_commits
# It's necessary to temporarily change the owner to sysadmin so that
# the system controller can push the files to the subcloud, since the files
# are in the folders only the root can access but the synchronize only
# support passwordless sysadmin to execute ssh and rsync.
- name: Temporarily change the ownership of {{ usm_software_dir }}
file:
path: "{{ usm_software_dir }}"
state: directory
owner: sysadmin
recurse: yes
- name: Copy system controller {{ usm_metadata_dir }} to subcloud {{ tmp_metadata_sync_dir }}
copy:
src: "{{ usm_metadata_dir }}"
dest: "{{ tmp_metadata_sync_dir }}"
force: true
- name: Copy system controller {{ ostree_metadata_commits_central }} to subcloud {{ tmp_metadata_sync_dir }}
copy:
src: "{{ ostree_metadata_commits_central }}"
dest: "{{ tmp_metadata_sync_dir }}"
force: true
# Switch from command to script module to run the ostree-metadata-sync.sh script
# on the system controller as it does not exist on N-1 release e.g. 22.12
- name: Synchronizing system controller ostree commits on subcloud
script: "{{ role_path }}/files/ostree-metadata-sync.sh --sw-version {{ software_version }}
sync-subcloud"
register: sync_software_commits
- name: Show sync output
debug:
msg:
- "sync_software_commits:"
- "rc: {{ sync_software_commits.rc }}"
- "stderr: {{ sync_software_commits.stderr }}"
- "stdout: {{ sync_software_commits.stdout }}"
# We want to transfer the rel-MM-mm directories that may exist in the system
# controller to the subcloud. There will always be at least one, which corresponds
# to the deployed base release, for example rel-24.09.0. This task should not fail,
# if it fails the playbook should be aborted.
- name: Copy system controller deployed release directory to subcloud
synchronize:
mode: "push"
src: "{{ usm_software_dir }}/rel-{{ item }}"
dest: "{{ usm_software_dir }}/"
rsync_opts: "--delete"
with_items: "{{ system_controller_releases }}"
register: releases_transfer
retries: 3
delay: 2
until: releases_transfer.rc == 0
# We want to check if the software-script directory exists on the system controller
# to ensure copying to the subcloud. This directory is created when a new patch is
# deployed, so it does not exist if only the base release is deployed, for example
# 24.09.0.
- name: Check if {{ usm_software_scripts_dir }} directory exists
stat:
path: "{{ usm_software_scripts_dir }}"
register: software_scripts_exists
delegate_to: localhost
# Only if the directory exists, it will be transferred to the subcloud.
# We cannot deploy a patch if the directory does not exist, therefore the playbook
# must abort if the transfer fails.
- name: Copy system controller {{ usm_software_scripts_dir }} to subcloud
synchronize:
mode: "push"
src: "{{ usm_software_scripts_dir }}"
dest: "{{ usm_software_dir }}/"
rsync_opts: "--delete"
register: scripts_transfer
retries: 3
delay: 2
until: scripts_transfer.rc == 0
when: software_scripts_exists.stat.exists
always:
- name: Restore the ownership of {{ usm_software_dir }}
file:
path: "{{ usm_software_dir }}"
state: directory
owner: root
recurse: yes
- name: Restore the ownership of {{ tmp_metadata_sync_dir }}
file:
path: "{{ tmp_metadata_sync_dir }}"
state: directory
owner: sysadmin
recurse: yes
- name: Synchronize software between controllers
command: "{{ usm_scripts_dir }}/controllers-software-sync"
- name: Synchronize {{ release_feed }} directory between controllers
command: "{{ usm_scripts_dir }}/sync-controllers-feed --feed={{ release_feed }}"
become: true