aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--kolla/common/sources.yaml55
-rw-r--r--kolla/docker/grafana/Dockerfile.j27
-rw-r--r--kolla/docker/ironic/ironic-conductor/Dockerfile.j25
-rw-r--r--kolla/docker/keystone/keystone-api/Dockerfile.j248
-rw-r--r--kolla/docker/keystone/keystone-api/extend_start.sh46
-rw-r--r--kolla/docker/keystone/keystone-api/keystone_bootstrap.sh66
-rw-r--r--kolla/docker/mariadb-server/Dockerfile.j22
-rw-r--r--kolla/docker/mariadb-server/backup_replica.sh149
-rw-r--r--kolla/docker/ovn/ovn-sb-db-relay/Dockerfile.j26
-rw-r--r--kolla/image/kolla_worker.py5
-rw-r--r--kolla/image/tasks.py6
-rw-r--r--kolla/template/repos.yaml2
-rw-r--r--kolla/tests/test_build.py42
-rw-r--r--lint-requirements.txt2
-rw-r--r--releasenotes/notes/bug-2165921-a70d2839ab32f423.yaml7
-rw-r--r--releasenotes/notes/bug-2166075-ea3b86dd40834b08.yaml5
-rw-r--r--releasenotes/notes/bug-2167459-3dbfafe10ea28fdc.yaml5
-rw-r--r--releasenotes/notes/deprecate-keystone-container-87d598bc05bc8ee5.yaml5
-rw-r--r--releasenotes/notes/ironic-vm-boot-4b0dfbf6ae60e5ba.yaml8
-rw-r--r--releasenotes/notes/update-external-components-419631c0a728a61e.yaml7
-rw-r--r--releasenotes/notes/update-external-components-55c57492253a6d19.yaml16
-rw-r--r--releasenotes/notes/update-external-components-97b947c8fdb88ac9.yaml7
-rw-r--r--releasenotes/notes/update-magnum-conductor-plugin-helm-6afa6c8dc5a98d5a.yaml5
-rw-r--r--releasenotes/notes/update-prometheus-mtail-4d73dd09f088a408.yaml4
-rw-r--r--releasenotes/source/2026.2.rst6
-rw-r--r--releasenotes/source/index.rst1
-rw-r--r--roles/kolla-build-config/templates/kolla-build.conf.j22
-rw-r--r--zuul.d/project.yaml1
-rw-r--r--zuul.d/scenarios/lets-encrypt.yaml12
29 files changed, 339 insertions, 193 deletions
diff --git a/kolla/common/sources.yaml b/kolla/common/sources.yaml
index 5d6a74c5c..db892daa8 100644
--- a/kolla/common/sources.yaml
+++ b/kolla/common/sources.yaml
@@ -35,11 +35,11 @@ etcd:
# NOTE(mnasiadka): lts_branch pins check_sources.py to the 3.6.x
# release series instead of jumping to the latest major.minor.
lts_branch: "3.6"
- version: "3.6.14"
+ version: "3.6.15"
type: "url"
sha256:
- amd64: "ffe840ff9295808e88cce2794a18a5ac87f12a5203c8314d0bf6aa119b41bac5"
- arm64: "fa1b80565ee6fc2df1ae6f57a508b221f3ecc7d591c317c581cd8281b0842b3e"
+ amd64: "b51d86e6bff2168de5ba8cd631c0fe6c785c7a1b32b083079f5677d6b7e2772c"
+ arm64: "567d9b8fa9e75b349600d2b64ef9bf6bc6d512cea75a2ce1c39b1b3046131244"
location: "https://github.com/etcd-io/etcd/releases/download/v${version}/etcd-v${version}-linux-${debian_arch}.tar.gz"
glance-base:
type: "url"
@@ -116,24 +116,25 @@ kolla-toolbox:
type: "url"
location: "$tarballs_base/openstack/requirements/requirements-${openstack_branch}.tar.gz"
letsencrypt-lego:
- version: "v5.4.1"
+ lts_branch: "4"
+ version: "v4.35.2"
type: "url"
sha256:
- amd64: "ebb33f1bead5a7c99dd46f1c5734b44cf1eab5b5c12faf397cd14d50a5916419"
- arm64: "8494c06bde449ac4d65c726b7ea50d67ac61f422e698c9b78b47778445b098f2"
+ amd64: "ee5be4bf457de8e3efa86a51651c75c87f0ee0e4e9f3ae14f6034d68365770f3"
+ arm64: "e1f153179098d27ce044aaaa168c0e323d50ae71b0f1a147aa8ae49ac6b14d89"
location: "https://github.com/go-acme/lego/releases/download/${version}/lego_${version}_linux_${debian_arch}.tar.gz"
magnum-base:
type: "url"
location: "$tarballs_base/openstack/magnum/magnum-${openstack_branch}.tar.gz"
magnum-conductor-plugin-helm:
- version: "v4.2.4"
+ version: "v4.3.0"
type: "url"
# NOTE(mnasiadka): location points to get.helm.sh, but
# check_sources needs github releases access
github: "helm/helm"
sha256:
- amd64: "c306b46f719b0a4da32d0f78ee21bf90ce8d602f15b22ab753f0674d1670a7f3"
- arm64: "564de2191b881e9f71b5606b25345821ea1682f06ab90499d3ab22b530176da1"
+ amd64: "86584a54def73570558f66f5111cc53dfed56689637ae32c1201205d494f54fb"
+ arm64: "31c5794dd55c66a51e6b7d2e2ac7a114ae8b1de41ff1d9ba51748ac973b06a08"
location: "https://get.helm.sh/helm-${version}-linux-${debian_arch}.tar.gz"
manila-base:
type: "url"
@@ -204,11 +205,11 @@ placement-base:
type: "url"
location: "$tarballs_base/openstack/placement/placement-${openstack_branch}.tar.gz"
prometheus-alertmanager:
- version: "0.34.0"
+ version: "0.34.1"
type: "url"
sha256:
- amd64: "19c75a11d8c03dc4ade7abdbddfb3a8f28c9e7b000d0849cda0cd71dffd74a03"
- arm64: "a96ef16598ddc58e84d28167b3352b30e3205698d76c56ef467e4504d7664da4"
+ amd64: "265b9d1e55ef0d5306a436018af6d2b686c2ce051f03d968f7464ecb1372a7e8"
+ arm64: "d98d6cbaf52151c7e76e24355fec88b11cebcb9875d4cdd8b76ddce7a7e5535c"
location: "https://github.com/prometheus/alertmanager/releases/download/v${version}/alertmanager-${version}.linux-${debian_arch}.tar.gz"
prometheus-blackbox-exporter:
version: "0.28.0"
@@ -218,11 +219,11 @@ prometheus-blackbox-exporter:
arm64: "63312be0983d85e5109710a7dc93df3051157ae581853fa3655d171cc1b2806e"
location: "https://github.com/prometheus/blackbox_exporter/releases/download/v${version}/blackbox_exporter-${version}.linux-${debian_arch}.tar.gz"
prometheus-cadvisor:
- version: "0.60.5"
+ version: "0.60.6"
type: "url"
sha256:
- amd64: "6f258bed28113218c88729634c47ead8d928b81b1504b75fd911b98d29003a87"
- arm64: "6f93087c114bc64a7b8d5c4148190b4d9b95511b9bf023246ce4c76dc448a48a"
+ amd64: "c381c2c911bc43d465d1e0eaff60f96d58c031c409bddf06da0316fdde8a9296"
+ arm64: "d788162d9deea8aa024fd79a0a685df90a987362d8f0e580f822474c1fbef7f9"
location: "https://github.com/google/cadvisor/releases/download/v${version}/cadvisor-v${version}-linux-${debian_arch}"
prometheus-elasticsearch-exporter:
version: "1.11.0"
@@ -232,11 +233,11 @@ prometheus-elasticsearch-exporter:
arm64: "7020d10e29896d329cecc7bfe2e90dcc376d68fc0c75ac27014af3747870ce1f"
location: "https://github.com/prometheus-community/elasticsearch_exporter/releases/download/v${version}/elasticsearch_exporter-${version}.linux-${debian_arch}.tar.gz"
prometheus-libvirt-exporter:
- version: "2.5.0"
+ version: "2.6.0"
type: "url"
sha256:
- amd64: "07a49f3d0424259eba88cbc41310017fbbbd6d8ce0b2a0e4dfad3d973b55f558"
- arm64: "4d13a4a930adabc9c2be8c83c7a8bb2b3e81d8743e9b645590f3d28311e1e8cb"
+ amd64: "1820ace3d38feebaf35ef2823ada1e95b538a080074c3f362caf39a7d3e39e91"
+ arm64: "b8d3bfbe590d1f2db4faac48984d5b2bcf2cfa525c39f9a8d307912220307550"
location: "https://github.com/inovex/prometheus-libvirt-exporter/releases/download/v${version}/prometheus-libvirt-exporter-${version}.linux-${debian_arch}.tar.gz"
prometheus-memcached-exporter:
version: "0.17.0"
@@ -246,11 +247,11 @@ prometheus-memcached-exporter:
arm64: "d1abf0ef1196ff5de5cf3462eb962b4a3d6733327951ae6d81c062902b5f2a60"
location: "https://github.com/prometheus/memcached_exporter/releases/download/v${version}/memcached_exporter-${version}.linux-${debian_arch}.tar.gz"
prometheus-mtail:
- version: "3.4.11"
+ version: "3.4.14"
type: "url"
sha256:
- amd64: "641a85ae818d8218ea4fc4bfde73b3dcea2b2bdbbc6cfb31c0d94091101c9c9e"
- arm64: "0fd30fc3430f36e984bfecdfda47e8b276ac8e85418596f324f36368e3e64b12"
+ amd64: "a01c7713d97c8725067e3f6cf2a5dccccb7aee62c8af57ffcff3a658f48b1b29"
+ arm64: "05c484b6a03510f8e6dfffccfe43453e71d357168c157342448e174f3263ca22"
location: "https://github.com/jaqx0r/mtail/releases/download/v${version}/mtail_${version}_linux_${debian_arch}.tar.gz"
prometheus-mysqld-exporter:
version: "0.20.0"
@@ -284,18 +285,18 @@ prometheus-server:
# NOTE(mnasiadka): lts_branch pins check_sources.py to the 3.13.x
# release series instead of jumping to the latest major.minor.
lts_branch: "3.13"
- version: "3.13.2"
+ version: "3.13.3"
type: "url"
sha256:
- amd64: "0e8c4d46101bd025ea8265e377d2caabc57f488fc1be1c367f37db69ea41be6f"
- arm64: "7cecb17a6f41d59814e1a0581a1f81f79051ad5973d1ecf39e23a9f747d6572a"
+ amd64: "b349c732d8a853e657d0e7ae1bbad4d11b586615fb65fdc59d896b9f869c001e"
+ arm64: "aa9be9c36608e7ab7cc089726195d0e4fa74f87b330538df9d30d3da1f2b0e18"
location: "https://github.com/prometheus/prometheus/releases/download/v${version}/prometheus-${version}.linux-${debian_arch}.tar.gz"
prometheus-valkey-exporter:
- version: "1.90.0"
+ version: "1.92.1"
type: "url"
sha256:
- amd64: "311205fdc6ea2fccd6368de32e0cbd1497d10bffd61e51cad7334a3898e9d508"
- arm64: "ddea9ed55be95e7588d7dcc03394d7b1e13c956c94f65da576b25d95c3d59c73"
+ amd64: "60e9819172ec1c954bad9b44ba0b15ef064e8551bd74461d0ed1a7585bb2c6ad"
+ arm64: "9aecfb030b173516266773e7d88256bedf414e6a552afc385cbb1ecd49f26832"
location: "https://github.com/oliver006/redis_exporter/releases/download/v${version}/redis_exporter-v${version}.linux-${debian_arch}.tar.gz"
skyline-apiserver:
type: "url"
diff --git a/kolla/docker/grafana/Dockerfile.j2 b/kolla/docker/grafana/Dockerfile.j2
index 971994baf..a3a2210e5 100644
--- a/kolla/docker/grafana/Dockerfile.j2
+++ b/kolla/docker/grafana/Dockerfile.j2
@@ -24,11 +24,14 @@ COPY extend_start.sh /usr/local/bin/kolla_extend_start
{% block grafana_plugins_install %}
-{% set grafana_default_plugins = ['grafana-opensearch-datasource'] %}
+{% set grafana_default_plugins = [
+ 'grafana-opensearch-datasource',
+ 'prometheus'
+] %}
{% set grafana_plugins = grafana_default_plugins | customizable("plugins") %}
{% if grafana_plugins | length > 0 %}
-RUN {{ (['grafana-cli plugins install %s'] * grafana_plugins | length ) | join(' && ') | format(*grafana_plugins) }}
+RUN {{ (['grafana cli plugins install %s'] * grafana_plugins | length ) | join(' && ') | format(*grafana_plugins) }}
{% endif %}
{% endblock %}
diff --git a/kolla/docker/ironic/ironic-conductor/Dockerfile.j2 b/kolla/docker/ironic/ironic-conductor/Dockerfile.j2
index 40525b620..cef504ca3 100644
--- a/kolla/docker/ironic/ironic-conductor/Dockerfile.j2
+++ b/kolla/docker/ironic/ironic-conductor/Dockerfile.j2
@@ -25,7 +25,8 @@ LABEL maintainer="{{ maintainer }}" name="{{ image_name }}"
'systemd-udev',
'util-linux',
'xfsprogs',
- 'xorriso'
+ 'xorriso',
+ 'zstd'
] %}
{% if base_arch in ['x86_64'] %}
{% set ironic_conductor_packages = ironic_conductor_packages + [
@@ -48,8 +49,10 @@ LABEL maintainer="{{ maintainer }}" name="{{ image_name }}"
'python3-systemd',
'qemu-utils',
'shellinabox',
+ 'syslinux-common',
'udev',
'xfsprogs',
+ 'zstd'
] %}
{% endif %}
diff --git a/kolla/docker/keystone/keystone-api/Dockerfile.j2 b/kolla/docker/keystone/keystone-api/Dockerfile.j2
new file mode 100644
index 000000000..df2003f10
--- /dev/null
+++ b/kolla/docker/keystone/keystone-api/Dockerfile.j2
@@ -0,0 +1,48 @@
+FROM {{ namespace }}/{{ image_prefix }}keystone-base:{{ tag }}
+{% block labels %}
+LABEL maintainer="{{ maintainer }}" name="{{ image_name }}"
+{% endblock %}
+
+{% block keystone_header %}{% endblock %}
+
+{% import "macros.j2" as macros with context %}
+
+{{ macros.kolla_enable_base_repos() }}
+
+{% if base_package_type == 'rpm' %}
+ {% set keystone_packages = [
+ 'krb5-devel',
+ ] %}
+{% elif base_package_type == 'deb' %}
+ {% set keystone_packages = [
+ 'libkrb5-dev',
+ ] %}
+{% endif %}
+{{ macros.install_packages(keystone_packages | customizable("packages")) }}
+
+{% set keystone_pip_packages = [
+ 'requests-kerberos',
+] %}
+
+RUN {{ macros.install_pip(keystone_pip_packages | customizable("pip_packages")) }}
+
+ADD plugins-archive /
+
+{% set keystone_plugins_pip_packages = [
+ '/plugins/*',
+] %}
+
+COPY keystone_bootstrap.sh /usr/local/bin/kolla_keystone_bootstrap
+COPY extend_start.sh /usr/local/bin/kolla_extend_start
+
+RUN chmod 644 /usr/local/bin/kolla_extend_start \
+ && chmod 755 /usr/local/bin/kolla_keystone_bootstrap \
+ && if [ "$(ls /plugins)" ]; then \
+ {{ macros.install_pip(keystone_plugins_pip_packages) }}; \
+ fi
+
+{{ macros.kolla_patch_sources() }}
+
+{% block keystone_footer %}{% endblock %}
+{% block footer %}{% endblock %}
+{{ macros.kolla_cleanup_repos() }}
diff --git a/kolla/docker/keystone/keystone-api/extend_start.sh b/kolla/docker/keystone/keystone-api/extend_start.sh
new file mode 100644
index 000000000..b45c94d0d
--- /dev/null
+++ b/kolla/docker/keystone/keystone-api/extend_start.sh
@@ -0,0 +1,46 @@
+#!/bin/bash
+
+# Create log dir for Keystone logs
+KEYSTONE_LOG_DIR="/var/log/kolla/keystone"
+if [[ ! -d "${KEYSTONE_LOG_DIR}" ]]; then
+ mkdir -p ${KEYSTONE_LOG_DIR}
+fi
+if [[ $(stat -c %U:%G ${KEYSTONE_LOG_DIR}) != "keystone:kolla" ]]; then
+ chown keystone:kolla ${KEYSTONE_LOG_DIR}
+fi
+if [ ! -f "${KEYSTONE_LOG_DIR}/keystone.log" ]; then
+ touch ${KEYSTONE_LOG_DIR}/keystone.log
+fi
+if [[ $(stat -c %U:%G ${KEYSTONE_LOG_DIR}/keystone.log) != "keystone:keystone" ]]; then
+ chown keystone:keystone ${KEYSTONE_LOG_DIR}/keystone.log
+fi
+if [[ $(stat -c %a ${KEYSTONE_LOG_DIR}) != "755" ]]; then
+ chmod 755 ${KEYSTONE_LOG_DIR}
+fi
+
+EXTRA_KEYSTONE_MANAGE_ARGS=${EXTRA_KEYSTONE_MANAGE_ARGS-}
+# Upgrade and exit if KOLLA_UPGRADE variable is set. This catches all cases
+# of the KOLLA_UPGRADE variable being set, including empty.
+if [[ "${!KOLLA_UPGRADE[@]}" ]]; then
+ # TODO(duonghq): check doctor result here
+ # TODO: find reason why doctor failed in gate
+ # sudo -H -u keystone keystone-manage doctor
+ sudo -H -u keystone keystone-manage ${EXTRA_KEYSTONE_MANAGE_ARGS} db_sync --expand
+ sudo -H -u keystone keystone-manage ${EXTRA_KEYSTONE_MANAGE_ARGS} db_sync --migrate
+ exit 0
+fi
+
+# Contract database and exit if KOLLA_FINISH_UPGRADE variable is set.
+# This catches all cases of the KOLLA_FINISH_UPGRADE variable being set,
+# including empty.
+if [[ "${!KOLLA_FINISH_UPGRADE[@]}" ]]; then
+ sudo -H -u keystone keystone-manage ${EXTRA_KEYSTONE_MANAGE_ARGS} db_sync --contract
+ exit 0
+fi
+
+# Bootstrap and exit if KOLLA_BOOTSTRAP variable is set. This catches all cases
+# of the KOLLA_BOOTSTRAP variable being set, including empty.
+if [[ "${!KOLLA_BOOTSTRAP[@]}" ]]; then
+ sudo -H -u keystone keystone-manage ${EXTRA_KEYSTONE_MANAGE_ARGS} db_sync
+ exit 0
+fi
diff --git a/kolla/docker/keystone/keystone-api/keystone_bootstrap.sh b/kolla/docker/keystone/keystone-api/keystone_bootstrap.sh
new file mode 100644
index 000000000..1b04d99b6
--- /dev/null
+++ b/kolla/docker/keystone/keystone-api/keystone_bootstrap.sh
@@ -0,0 +1,66 @@
+#!/bin/bash
+
+set -o pipefail
+
+# NOTE(SamYaple): Kolla needs to wraps `keystone-manage bootstrap` to ensure
+# any change is reported correctly for idempotency. This script will exit with
+# valid json that can be parsed with information about if the task has failed
+# and if anything changed.
+
+USERNAME=$1
+PASSWORD=$2
+if [ -z "$PASSWORD" ]; then
+ # Avoid having the password always come in via CLI (which makes
+ # it show up in things like ara)
+ PASSWORD="$OS_BOOTSTRAP_PASSWORD"
+fi
+PROJECT=$3
+ROLE=$4
+if [ $# -ge 8 ]; then
+ # ignored ADMIN_URL compat mode
+ # ADMIN_URL=$5
+ INTERNAL_URL=$6
+ PUBLIC_URL=$7
+ REGION=$8
+else
+ # no ADMIN_URL modern mode
+ INTERNAL_URL=$5
+ PUBLIC_URL=$6
+ REGION=$7
+fi
+
+function fail_json {
+ echo '{"failed": true, "msg": "'$1'", "changed": true}'
+ exit 1
+}
+
+function exit_json {
+ echo '{"failed": false, "changed": '"${changed}"'}'
+}
+
+changed="false"
+# NOTE(mgoddard): pipe through cat -v to remove unprintable control characters
+# which prevent JSON decoding.
+# NOTE(yoctozepto): also apply sed to escape double quotation marks
+# and backslashes
+keystone_bootstrap=$(keystone-manage bootstrap --bootstrap-username "${USERNAME}" --bootstrap-password "${PASSWORD}" --bootstrap-project-name "${PROJECT}" --bootstrap-role-name "${ROLE}" --bootstrap-internal-url "${INTERNAL_URL}" --bootstrap-public-url "${PUBLIC_URL}" --bootstrap-service-name "keystone" --bootstrap-region-id "${REGION}" 2>&1 | cat -v | sed 's/\\/\\\\/g' | sed 's/"/\\"/g')
+if [[ $? != 0 ]]; then
+ fail_json "${keystone_bootstrap}"
+fi
+
+changed=$(echo "${keystone_bootstrap}" | awk '
+ /Domain default already exists, skipping creation./ ||
+ /Project '"${PROJECT}"' already exists, skipping creation./ ||
+ /User '"${USERNAME}"' already exists, skipping creation./ ||
+ /Role '"${ROLE}"' exists, skipping creation./ ||
+ /User '"${USERNAME}"' already has '"${ROLE}"' on '"${PROJECT}"'./ ||
+ /Region '"${REGION}"' exists, skipping creation./ ||
+ /Skipping internal endpoint as already created/ ||
+ /Skipping public endpoint as already created/ {count++}
+ END {
+ if (count == 9) changed="false"; else changed="true"
+ print changed
+ }'
+)
+
+exit_json
diff --git a/kolla/docker/mariadb-server/Dockerfile.j2 b/kolla/docker/mariadb-server/Dockerfile.j2
index a9a84bf73..436953e80 100644
--- a/kolla/docker/mariadb-server/Dockerfile.j2
+++ b/kolla/docker/mariadb-server/Dockerfile.j2
@@ -54,12 +54,10 @@ COPY mariadb_sudoers /etc/sudoers.d/kolla_mariadb_sudoers
COPY extend_start.sh /usr/local/bin/kolla_extend_start
COPY security_reset.expect /usr/local/bin/kolla_security_reset
COPY backup.sh /usr/local/bin/kolla_mariadb_backup.sh
-COPY backup_replica.sh /usr/local/bin/kolla_mariadb_backup_replica.sh
RUN chmod 644 /usr/local/bin/kolla_extend_start \
&& chmod 755 /usr/local/bin/kolla_security_reset \
/usr/local/bin/kolla_mariadb_backup.sh \
- /usr/local/bin/kolla_mariadb_backup_replica.sh \
&& chmod 750 /etc/sudoers.d \
&& chmod 440 /etc/sudoers.d/kolla_mariadb_sudoers \
&& rm -rf /var/lib/mysql/*
diff --git a/kolla/docker/mariadb-server/backup_replica.sh b/kolla/docker/mariadb-server/backup_replica.sh
deleted file mode 100644
index fe10bc61b..000000000
--- a/kolla/docker/mariadb-server/backup_replica.sh
+++ /dev/null
@@ -1,149 +0,0 @@
-#!/usr/bin/env bash
-
-set -eu
-set -o pipefail
-
-BACKUP_DIR=/backup/
-DEFAULT_MY_CNF="/etc/mysql/my.cnf"
-REPLICA_MY_CNF="$(mktemp)"
-RETRY_INTERVAL=5 # Interval between retries (in seconds)
-MAX_RETRIES=12 # Max retries (12 retries * 5 seconds = 60 seconds)
-VERIFY_DB_SERVER_CERT="${VERIFY_DB_SERVER_CERT:=FALSE}"
-
-# Cleanup function to remove the REPLICA_MY_CNF file
-cleanup() {
- rm -f "${REPLICA_MY_CNF}"
-}
-
-# Set trap to ensure cleanup occurs on exit or error
-trap cleanup EXIT
-
-cd "${BACKUP_DIR}"
-
-# Execute a full backup
-backup_full() {
- echo "Taking a full backup"
- LAST_FULL_DATE=$(date +%d-%m-%Y-%s)
- BACKUP_FILE="backup-full-${LAST_FULL_DATE}.mbs.gz"
- BACKUP_PATH="${BACKUP_DIR}/full-${LAST_FULL_DATE}"
- mkdir -p "${BACKUP_PATH}"
-
- mariabackup \
- --defaults-file="${REPLICA_MY_CNF}" \
- --backup \
- --stream=mbstream \
- --history="${LAST_FULL_DATE}" \
- | gzip > "${BACKUP_PATH}/${BACKUP_FILE}"
-
- echo "${BACKUP_PATH}/${BACKUP_FILE}" > "${BACKUP_DIR}/last_full_file"
-}
-
-# Execute an incremental backup
-backup_incremental() {
- if [ ! -r "${BACKUP_DIR}/last_full_file" ]; then
- echo "Error: No full backup file found."
- exit 1
- fi
-
- FULL_BACKUP_FILE=$(cat "${BACKUP_DIR}/last_full_file")
- LAST_FULL_DATE=$(basename "$(dirname "${FULL_BACKUP_FILE}")" | sed 's/^full-//')
- NOW=$(date +%H-%M-%S-%d-%m-%Y)
- INCR_DIR="${BACKUP_DIR}/incr-${NOW}-since-${LAST_FULL_DATE}"
- mkdir -p "${INCR_DIR}"
-
- # Temp dir for full base restore
- TMP_BASEDIR=$(mktemp -d)
-
- echo "Decompressing full backup to temp dir: ${TMP_BASEDIR}"
- gunzip -c "${FULL_BACKUP_FILE}" | mbstream -x -C "${TMP_BASEDIR}"
-
- mariabackup \
- --defaults-file="${REPLICA_MY_CNF}" \
- --backup \
- --stream=mbstream \
- --incremental-basedir="${TMP_BASEDIR}" \
- --history="incr-${NOW}" \
- | gzip > "${INCR_DIR}/backup-incremental-${NOW}.mbs.gz"
-
- rm -rf "${TMP_BASEDIR}"
-}
-
-# Retry logic for database queries
-retry_mysql_query() {
- local query="$1"
- local result=""
- local attempt=1
-
- while [ ${attempt} -le ${MAX_RETRIES} ]; do
- result=$(mariadb --ssl-verify-server-cert="${VERIFY_DB_SERVER_CERT}" -h "${HOST}" -u "${USER}" -p"${PASS}" -s -N -e "${query}" 2>/dev/null || true)
- if [ -n "${result}" ]; then
- echo "${result}"
- return 0
- fi
- echo "Attempt ${attempt}/${MAX_RETRIES} failed. Retrying in ${RETRY_INTERVAL} seconds..."
- sleep "${RETRY_INTERVAL}"
- attempt=$((attempt + 1))
- done
-
- echo "Error: Failed to execute the query after ${MAX_RETRIES} attempts."
- return 1
-}
-
-get_and_set_replica_server() {
- HOST="$(grep '^host' "${DEFAULT_MY_CNF}" | awk -F '=' '{print $2}' | xargs)"
- USER="$(grep '^user' "${DEFAULT_MY_CNF}" | awk -F '=' '{print $2}' | xargs)"
- PASS="$(grep '^password' "${DEFAULT_MY_CNF}" | awk -F '=' '{print $2}' | xargs)"
-
- ALL_HOSTS_SELECT="SELECT REGEXP_REPLACE(VARIABLE_VALUE, ':[0-9]*','') FROM information_schema.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_incoming_addresses';"
- ALL_HOSTS=$(retry_mysql_query "${ALL_HOSTS_SELECT}")
- if [ -z "${ALL_HOSTS}" ]; then
- echo "Backup failed due to inability to fetch a list of servers."
- exit 1
- fi
-
- ACTIVE_HOST_SELECT='SELECT @@hostname;'
- ACTIVE_HOST=$(retry_mysql_query "${ACTIVE_HOST_SELECT}" | xargs getent hosts | awk '{print $1}')
- if [ -z "${ACTIVE_HOST}" ]; then
- echo "Backup failed due to inability to fetch active host."
- exit 1
- fi
-
- # Multinode
- if echo "${ALL_HOSTS}" | grep -q ','; then
- for server in $(echo "${ALL_HOSTS}" | tr ',' '\n'); do
- if [[ "${server}" != "${ACTIVE_HOST}" ]]; then
- REPLICA_HOST="${server}"
- break
- fi
- done
- # Single node
- else
- REPLICA_HOST="${ALL_HOSTS}"
- fi
- if [ -z "${REPLICA_HOST}" ]; then
- echo "Backup failed due to inability to determine replica host."
- exit 1
- fi
-
- cp "${DEFAULT_MY_CNF}" "${REPLICA_MY_CNF}"
- sed -i "s/${HOST}/${REPLICA_HOST}/g" "${REPLICA_MY_CNF}"
-}
-
-if [ -n "${BACKUP_TYPE}" ]; then
- get_and_set_replica_server
- case "${BACKUP_TYPE}" in
- "full")
- backup_full
- ;;
- "incremental")
- backup_incremental
- ;;
- *)
- echo "Only full or incremental options are supported."
- exit 1
- ;;
- esac
-else
- echo "You need to specify either full or incremental backup options."
- exit 1
-fi
diff --git a/kolla/docker/ovn/ovn-sb-db-relay/Dockerfile.j2 b/kolla/docker/ovn/ovn-sb-db-relay/Dockerfile.j2
index 1d1761033..667c89afd 100644
--- a/kolla/docker/ovn/ovn-sb-db-relay/Dockerfile.j2
+++ b/kolla/docker/ovn/ovn-sb-db-relay/Dockerfile.j2
@@ -7,12 +7,6 @@ LABEL maintainer="{{ maintainer }}" name="{{ image_name }}"
{% import "macros.j2" as macros with context %}
-{% block ovn_sb_db_relay_ovn_ctl %}
-{# TODO(mnasiadka): Switch to 25.03 branch when available, ideally rpm/deb packages will be
- available. #}
-RUN curl -o /usr/share/ovn/scripts/ovn-ctl https://raw.githubusercontent.com/ovn-org/ovn/refs/heads/main/utilities/ovn-ctl
-{% endblock %}
-
COPY extend_start.sh /usr/local/bin/kolla_ovn_extend_start
RUN chmod 644 /usr/local/bin/kolla_ovn_extend_start
diff --git a/kolla/image/kolla_worker.py b/kolla/image/kolla_worker.py
index 92908a6c1..837bd797c 100644
--- a/kolla/image/kolla_worker.py
+++ b/kolla/image/kolla_worker.py
@@ -423,7 +423,7 @@ class KollaWorker(object):
if pip_args:
lines = content.split('\n')
for i, line in enumerate(lines):
- if line.startswith('FROM '):
+ if re.match(r'^FROM\s', line, re.IGNORECASE):
lines[i + 1:i + 1] = pip_args
break
content = '\n'.join(lines)
@@ -756,7 +756,8 @@ class KollaWorker(object):
image_name = os.path.basename(path)
canonical_name = (self.namespace + '/' + self.image_prefix +
image_name + ':' + self.tag)
- parent_search_pattern = re.compile(r'^FROM.*$', re.MULTILINE)
+ parent_search_pattern = re.compile(r'^FROM.*$',
+ re.MULTILINE | re.IGNORECASE)
match = re.search(parent_search_pattern, content)
if match:
parent_name = match.group(0).split(' ')[1]
diff --git a/kolla/image/tasks.py b/kolla/image/tasks.py
index ba2ade743..87dff5640 100644
--- a/kolla/image/tasks.py
+++ b/kolla/image/tasks.py
@@ -56,6 +56,12 @@ def normalize_tarinfo(tarinfo):
# unchanged. An integer mtime also stops tarfile's PAX writer
# emitting per-entry float-mtime extended headers.
tarinfo.mtime = 0
+
+ # Ensure directories are writable. Git repos contain directories
+ # such as .git/objects/pack/ with mode 0555, which prevents
+ # non-root users from re-extracting into an existing items_path
+ # on build retry.
+ tarinfo.mode |= 0o200
return tarinfo
diff --git a/kolla/template/repos.yaml b/kolla/template/repos.yaml
index 1ae76d137..71db00a30 100644
--- a/kolla/template/repos.yaml
+++ b/kolla/template/repos.yaml
@@ -73,7 +73,7 @@ ubuntu:
distro: True
ubuntu-cloud-archive:
url: "http://ubuntu-cloud.archive.canonical.com/ubuntu"
- suite: "noble-updates/{openstack_release_codename}"
+ suite: "noble-updates/gazpacho"
component: "main"
gpg_key: "/usr/share/keyrings/ubuntu-cloud-keyring.gpg"
erlang:
diff --git a/kolla/tests/test_build.py b/kolla/tests/test_build.py
index 0ada46eb6..7d7c58d0f 100644
--- a/kolla/tests/test_build.py
+++ b/kolla/tests/test_build.py
@@ -962,6 +962,48 @@ class KollaWorkerTest(base.TestCase):
self.assertRaises(jinja2.exceptions.SecurityError,
kolla.create_dockerfiles)
+ @mock.patch(engine_client)
+ def test_create_dockerfiles_pip_args_lowercase_from(self, mock_client):
+ tmpdir = self.useFixture(fixtures.TempDir()).path
+ base_dir = os.path.join(tmpdir, 'base')
+ os.makedirs(base_dir)
+ with open(os.path.join(base_dir, 'Dockerfile.j2'), 'w') as f:
+ f.write('from {{ base_distro }}:{{ base_distro_tag }}\n')
+ self.conf.set_override('pip_index_url', 'https://example.org/simple')
+ with mock.patch.object(build.KollaWorker, '_get_images_dir',
+ return_value=tmpdir):
+ kolla = build.KollaWorker(self.conf)
+ kolla.setup_working_dir()
+ kolla.find_dockerfiles()
+ kolla.create_dockerfiles()
+ dockerfile = os.path.join(kolla.working_dir, 'base', 'Dockerfile')
+ with open(dockerfile) as f:
+ content = f.read()
+ self.assertIn('ARG PIP_INDEX_URL', content)
+
+ @mock.patch(engine_client)
+ def test_build_image_list_parent_name_lowercase_from(self, mock_client):
+ tmpdir = self.useFixture(fixtures.TempDir()).path
+ base_dir = os.path.join(tmpdir, 'base')
+ os.makedirs(base_dir)
+ with open(os.path.join(base_dir, 'Dockerfile.j2'), 'w') as f:
+ f.write('FROM {{ base_distro }}:{{ base_distro_tag }}\n')
+ child_dir = os.path.join(tmpdir, 'child')
+ os.makedirs(child_dir)
+ with open(os.path.join(child_dir, 'Dockerfile.j2'), 'w') as f:
+ f.write('from {{ namespace }}/{{ image_prefix }}base:{{ tag }}\n')
+ with mock.patch.object(build.KollaWorker, '_get_images_dir',
+ return_value=tmpdir):
+ kolla = build.KollaWorker(self.conf)
+ kolla.setup_working_dir()
+ kolla.find_dockerfiles()
+ kolla.create_dockerfiles()
+ kolla.build_image_list()
+ expected_parent = '{}/{}base:{}'.format(
+ kolla.namespace, kolla.image_prefix, kolla.tag)
+ child = [i for i in kolla.images if i.name == 'child'][0]
+ self.assertEqual(expected_parent, child.parent_name)
+
def _get_matched_images(self, images):
return [image for image in images
if image.status == utils.Status.MATCHED]
diff --git a/lint-requirements.txt b/lint-requirements.txt
index 41f6c792e..e88fa52c4 100644
--- a/lint-requirements.txt
+++ b/lint-requirements.txt
@@ -1 +1 @@
-ansible-lint===26.8.0 # MIT
+ansible-lint===26.9.0 # MIT
diff --git a/releasenotes/notes/bug-2165921-a70d2839ab32f423.yaml b/releasenotes/notes/bug-2165921-a70d2839ab32f423.yaml
new file mode 100644
index 000000000..91f900ec4
--- /dev/null
+++ b/releasenotes/notes/bug-2165921-a70d2839ab32f423.yaml
@@ -0,0 +1,7 @@
+---
+fixes:
+ - |
+ Install the Prometheus datasource plugin for Grafana 13.2+.
+ Grafana 13.2 moved Prometheus to a standalone plugin, which
+ is not automatically installed in offline environments.
+ `LP#2165921 <https://launchpad.net/bugs/2165921>`__
diff --git a/releasenotes/notes/bug-2166075-ea3b86dd40834b08.yaml b/releasenotes/notes/bug-2166075-ea3b86dd40834b08.yaml
new file mode 100644
index 000000000..62dda913c
--- /dev/null
+++ b/releasenotes/notes/bug-2166075-ea3b86dd40834b08.yaml
@@ -0,0 +1,5 @@
+---
+fixes:
+ - |
+ Replace deprecated ``grafana-cli`` with ``grafana cli``.
+ `LP#2166075 <https://launchpad.net/bugs/2166075>`__
diff --git a/releasenotes/notes/bug-2167459-3dbfafe10ea28fdc.yaml b/releasenotes/notes/bug-2167459-3dbfafe10ea28fdc.yaml
new file mode 100644
index 000000000..ca6ba4080
--- /dev/null
+++ b/releasenotes/notes/bug-2167459-3dbfafe10ea28fdc.yaml
@@ -0,0 +1,5 @@
+---
+fixes:
+ - |
+ Fixes ironic-conductor failing to decompress zstd
+ compressed files. `LP#2167459 <https://launchpad.net/bugs/2167459>_`
diff --git a/releasenotes/notes/deprecate-keystone-container-87d598bc05bc8ee5.yaml b/releasenotes/notes/deprecate-keystone-container-87d598bc05bc8ee5.yaml
new file mode 100644
index 000000000..de925e0c6
--- /dev/null
+++ b/releasenotes/notes/deprecate-keystone-container-87d598bc05bc8ee5.yaml
@@ -0,0 +1,5 @@
+---
+deprecations:
+ - |
+ ``keystone`` container image has been deprecated in favor of newly
+ introduced (and identical) ``keystone-api`` container image.
diff --git a/releasenotes/notes/ironic-vm-boot-4b0dfbf6ae60e5ba.yaml b/releasenotes/notes/ironic-vm-boot-4b0dfbf6ae60e5ba.yaml
new file mode 100644
index 000000000..fe2835ac2
--- /dev/null
+++ b/releasenotes/notes/ironic-vm-boot-4b0dfbf6ae60e5ba.yaml
@@ -0,0 +1,8 @@
+---
+
+fixes:
+ - |
+ Syslinux is now installed in debian based ironic-conductor containers.
+ This fixes an issue where ironic python agent ramdisks would be missing
+ ldlinux.c32 and fail to boot on nodes with redfish-virtual-media boot
+ interface.
diff --git a/releasenotes/notes/update-external-components-419631c0a728a61e.yaml b/releasenotes/notes/update-external-components-419631c0a728a61e.yaml
new file mode 100644
index 000000000..baff1d3e6
--- /dev/null
+++ b/releasenotes/notes/update-external-components-419631c0a728a61e.yaml
@@ -0,0 +1,7 @@
+---
+upgrade:
+ - |
+ ``prometheus-mtail`` has been updated from ``3.4.13`` to ``3.4.14``.
+ - |
+ ``prometheus-valkey-exporter`` has been updated from ``1.92.0`` to
+ ``1.92.1``.
diff --git a/releasenotes/notes/update-external-components-55c57492253a6d19.yaml b/releasenotes/notes/update-external-components-55c57492253a6d19.yaml
new file mode 100644
index 000000000..e78d660cc
--- /dev/null
+++ b/releasenotes/notes/update-external-components-55c57492253a6d19.yaml
@@ -0,0 +1,16 @@
+---
+upgrade:
+ - |
+ ``etcd`` has been updated from ``3.6.14`` to ``3.6.15``.
+ - |
+ ``prometheus-alertmanager`` has been updated from ``0.34.0`` to ``0.34.1``.
+ - |
+ ``prometheus-cadvisor`` has been updated from ``0.60.5`` to ``0.60.6``.
+ - |
+ ``prometheus-libvirt-exporter`` has been updated from ``2.5.0`` to
+ ``2.6.0``.
+ - |
+ ``prometheus-mtail`` has been updated from ``3.4.12`` to ``3.4.13``.
+ - |
+ ``prometheus-valkey-exporter`` has been updated from ``1.91.1`` to
+ ``1.92.0``.
diff --git a/releasenotes/notes/update-external-components-97b947c8fdb88ac9.yaml b/releasenotes/notes/update-external-components-97b947c8fdb88ac9.yaml
new file mode 100644
index 000000000..d758f9412
--- /dev/null
+++ b/releasenotes/notes/update-external-components-97b947c8fdb88ac9.yaml
@@ -0,0 +1,7 @@
+---
+upgrade:
+ - |
+ ``prometheus-server`` has been updated from ``3.13.2`` to ``3.13.3``.
+ - |
+ ``prometheus-valkey-exporter`` has been updated from ``1.90.0`` to
+ ``1.91.1``.
diff --git a/releasenotes/notes/update-magnum-conductor-plugin-helm-6afa6c8dc5a98d5a.yaml b/releasenotes/notes/update-magnum-conductor-plugin-helm-6afa6c8dc5a98d5a.yaml
new file mode 100644
index 000000000..122ee7c67
--- /dev/null
+++ b/releasenotes/notes/update-magnum-conductor-plugin-helm-6afa6c8dc5a98d5a.yaml
@@ -0,0 +1,5 @@
+---
+upgrade:
+ - |
+ ``magnum-conductor-plugin-helm`` has been updated from ``4.2.4`` to
+ ``4.3.0``.
diff --git a/releasenotes/notes/update-prometheus-mtail-4d73dd09f088a408.yaml b/releasenotes/notes/update-prometheus-mtail-4d73dd09f088a408.yaml
new file mode 100644
index 000000000..a9c6e7ed8
--- /dev/null
+++ b/releasenotes/notes/update-prometheus-mtail-4d73dd09f088a408.yaml
@@ -0,0 +1,4 @@
+---
+upgrade:
+ - |
+ ``prometheus-mtail`` has been updated from ``3.4.11`` to ``3.4.12``.
diff --git a/releasenotes/source/2026.2.rst b/releasenotes/source/2026.2.rst
new file mode 100644
index 000000000..a423bf972
--- /dev/null
+++ b/releasenotes/source/2026.2.rst
@@ -0,0 +1,6 @@
+===========================
+2026.2 Series Release Notes
+===========================
+
+.. release-notes::
+ :branch: stable/2026.2
diff --git a/releasenotes/source/index.rst b/releasenotes/source/index.rst
index f49536313..c240c6a2f 100644
--- a/releasenotes/source/index.rst
+++ b/releasenotes/source/index.rst
@@ -9,6 +9,7 @@ Contents
:maxdepth: 2
unreleased
+ 2026.2
2026.1
2025.2
2025.1
diff --git a/roles/kolla-build-config/templates/kolla-build.conf.j2 b/roles/kolla-build-config/templates/kolla-build.conf.j2
index eddbdab14..07a50baae 100644
--- a/roles/kolla-build-config/templates/kolla-build.conf.j2
+++ b/roles/kolla-build-config/templates/kolla-build.conf.j2
@@ -10,7 +10,6 @@
{# Generate a section for every build source Zuul has a checkout for,
whether it's a required-project or a Depends-On. #}
-{% if not (is_upgrade | default(False) | bool) %}
{% for canonical_name, project in zuul['projects'].items() %}
{% if project.name in kolla_build_sources %}
{% set source_names = kolla_build_sources[project.name] %}
@@ -27,4 +26,3 @@ location = {{ ansible_env.PWD ~ '/' ~ project.src_dir }}
{% endif %}
{% endif %}
{% endfor %}
-{% endif %}
diff --git a/zuul.d/project.yaml b/zuul.d/project.yaml
index 3f6590f90..782a5c640 100644
--- a/zuul.d/project.yaml
+++ b/zuul.d/project.yaml
@@ -14,6 +14,7 @@
- kolla-scenario-cells
- kolla-scenario-cephadm
- kolla-scenario-ironic
+ - kolla-scenario-lets-encrypt
- kolla-scenario-mariadb
- kolla-scenario-masakari
- kolla-scenario-octavia
diff --git a/zuul.d/scenarios/lets-encrypt.yaml b/zuul.d/scenarios/lets-encrypt.yaml
new file mode 100644
index 000000000..9649d4ea6
--- /dev/null
+++ b/zuul.d/scenarios/lets-encrypt.yaml
@@ -0,0 +1,12 @@
+---
+- project-template:
+ name: kolla-scenario-lets-encrypt
+ description: |
+ Runs Kolla-Ansible Let's Encrypt scenario jobs.
+ check:
+ jobs:
+ - kolla-ansible-debian-trixie-lets-encrypt: &files
+ files:
+ - ^kolla/common/sources.yaml
+ - ^kolla/docker/(haproxy|httpd|letsencrypt)/
+ - kolla-ansible-ubuntu-noble-lets-encrypt: *files