From 38eefbf7ce1cace87d7d80100ea8648bb10630d4 Mon Sep 17 00:00:00 2001 From: Elod Illes Date: Thu, 21 May 2026 16:51:07 +0200 Subject: [PATCH 01/15] lib/tempest: Fix tempest verify-config Tempest is installed in venv-tempest virtual environment so that it always uses the correct upper constraints, etc. On the other hand 'tempest verify-config' is called via 'venv' virtualenv, which does not exist, so tox creates it, using upper constraints from master branch (defined in [venv]deps in tox), which can cause pip install failures if there are any conflicting upper constraint on master branch and the set up requirements. To fix this, the same venv-tempest virtual environment should be used, that was set up previously in the script. Change-Id: Ifb542d6f7d937a8a2020d97c10534467dbdf0051 Signed-off-by: Elod Illes --- lib/tempest | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/tempest b/lib/tempest index 1ebe9c5f1f..8680961fe4 100644 --- a/lib/tempest +++ b/lib/tempest @@ -791,7 +791,7 @@ function configure_tempest { # API Extensions # Run ``verify_tempest_config -ur`` to retrieve enabled extensions on API endpoints # NOTE(mtreinish): This must be done after auth settings are added to the tempest config - tox -evenv -- tempest verify-config -uro $tmp_cfg_file + tox -evenv-tempest -- tempest verify-config -uro $tmp_cfg_file # Neutron API Extensions From a1b0dcb24db9eb7e3463d4d5b940b94320ab890b Mon Sep 17 00:00:00 2001 From: Ghanshyam Maan Date: Wed, 17 Jun 2026 18:10:34 +0000 Subject: [PATCH 02/15] Remove setting of oslo_policy[enforce_scope] flag oslo_policy[enforce_scope] config option was added for the temporary transition to SRBAC and was deprecated. - https://lists.openstack.org/archives/list/openstack-discuss@lists.openstack.org/thread/M72AY5ABQFXQ7XHLVEGHLBBK4XFQGVFK/ To remove it from oslo.policy, we need to remove setting of it from devstack which makes scope enforcement enabled always without providing a way to disable it. oslo_policy[enforce_new_defaults] is still there and will be used to enable/disable the new defaults (until old defaults are not removed). Needed-By: https://review.opendev.org/c/openstack/oslo.policy/+/986475 Change-Id: Ib5afc734b711dd8fa22c6c91b5083888973b2815 Signed-off-by: Ghanshyam Maan --- .zuul.yaml | 2 +- functions-common | 2 +- lib/cinder | 16 ++++++++-------- lib/glance | 16 ++++++++-------- lib/keystone | 16 ++++++++-------- lib/neutron | 19 ++++++++++--------- lib/nova | 17 ++++++++++------- lib/placement | 16 ++++++++-------- lib/tempest | 12 ++++++------ stackrc | 10 +++++++--- 10 files changed, 67 insertions(+), 59 deletions(-) diff --git a/.zuul.yaml b/.zuul.yaml index a37520d93f..2d40df1988 100644 --- a/.zuul.yaml +++ b/.zuul.yaml @@ -747,7 +747,7 @@ This job runs the devstack with scope checks enabled. vars: devstack_localrc: - ENFORCE_SCOPE: true + ENFORCE_NEW_DEFAULTS: true - job: name: devstack-multinode diff --git a/functions-common b/functions-common index b3a4b57f01..aefa1fcef5 100644 --- a/functions-common +++ b/functions-common @@ -1121,7 +1121,7 @@ function is_ironic_hardware { } function is_ironic_enforce_scope { - is_service_enabled ironic && [[ "$IRONIC_ENFORCE_SCOPE" == "True" || "$ENFORCE_SCOPE" == "True" ]] && return 0 + is_service_enabled ironic && [[ "$IRONIC_ENFORCE_NEW_DEFAULTS" == "True" || "$IRONIC_ENFORCE_SCOPE" == "True" || "$ENFORCE_NEW_DEFAULTS" == "True" ]] && return 0 return 1 } diff --git a/lib/cinder b/lib/cinder index cdf1769b17..4510efe5e0 100644 --- a/lib/cinder +++ b/lib/cinder @@ -204,11 +204,13 @@ CINDER_CACHE_ENABLED_FOR_BACKENDS=${CINDER_CACHE_ENABLED_FOR_BACKENDS:-$CINDER_E # enable the cache for all cinder backends. CINDER_UPLOAD_OPTIMIZED_BACKENDS=${CINDER_UPLOAD_OPTIMIZED_BACKENDS:-$CINDER_ENABLED_BACKENDS} -# Flag to set the oslo_policy.enforce_scope. This is used to switch -# the Volume API policies to start checking the scope of token. by default, -# this flag is False. -# For more detail: https://docs.openstack.org/oslo.policy/latest/configuration/index.html#oslo_policy.enforce_scope -CINDER_ENFORCE_SCOPE=$(trueorfalse False CINDER_ENFORCE_SCOPE) +# Flag to set the oslo_policy.enforce_new_defaults. This is used to switch +# the Volume API policies to use the new defaults. +# CINDER_ENFORCE_SCOPE is a deprecated alias for CINDER_ENFORCE_NEW_DEFAULTS. +CINDER_ENFORCE_NEW_DEFAULTS=$(trueorfalse False CINDER_ENFORCE_NEW_DEFAULTS) +if [[ -n "${CINDER_ENFORCE_SCOPE}" ]]; then + CINDER_ENFORCE_NEW_DEFAULTS=$(trueorfalse False CINDER_ENFORCE_SCOPE) +fi # Functions # --------- @@ -426,11 +428,9 @@ function configure_cinder { iniset $CINDER_CONF coordination backend_url "etcd3+http://${SERVICE_HOST}:$ETCD_PORT?api_version=v3" fi - if [[ "$CINDER_ENFORCE_SCOPE" == True || "$ENFORCE_SCOPE" == True ]] ; then - iniset $CINDER_CONF oslo_policy enforce_scope true + if [[ "$CINDER_ENFORCE_NEW_DEFAULTS" == True || "$ENFORCE_NEW_DEFAULTS" == True ]] ; then iniset $CINDER_CONF oslo_policy enforce_new_defaults true else - iniset $CINDER_CONF oslo_policy enforce_scope false iniset $CINDER_CONF oslo_policy enforce_new_defaults false fi diff --git a/lib/glance b/lib/glance index 9495d345a3..070798c86c 100644 --- a/lib/glance +++ b/lib/glance @@ -97,11 +97,13 @@ GLANCE_TASKS_DIR=${GLANCE_MULTISTORE_FILE_IMAGE_DIR:=$DATA_DIR/os_glance_tasks_s GLANCE_USE_IMPORT_WORKFLOW=$(trueorfalse False GLANCE_USE_IMPORT_WORKFLOW) GLANCE_ENABLE_QUOTAS=$(trueorfalse True GLANCE_ENABLE_QUOTAS) -# Flag to set the oslo_policy.enforce_scope. This is used to switch -# This is used to disable the Image API policies scope and new defaults. -# By Default, it is True. -# For more detail: https://docs.openstack.org/oslo.policy/latest/configuration/index.html#oslo_policy.enforce_scope -GLANCE_ENFORCE_SCOPE=$(trueorfalse True GLANCE_ENFORCE_SCOPE) +# Flag to set the oslo_policy.enforce_new_defaults. This is used to switch +# This is used to switch the Image API policies to use new defaults. +# GLANCE_ENFORCE_SCOPE is a deprecated alias for GLANCE_ENFORCE_NEW_DEFAULTS. +GLANCE_ENFORCE_NEW_DEFAULTS=$(trueorfalse True GLANCE_ENFORCE_NEW_DEFAULTS) +if [[ -n "${GLANCE_ENFORCE_SCOPE}" ]]; then + GLANCE_ENFORCE_NEW_DEFAULTS=$(trueorfalse True GLANCE_ENFORCE_SCOPE) +fi # Flag to disable image format inspection on upload GLANCE_ENFORCE_IMAGE_FORMAT=$(trueorfalse True GLANCE_ENFORCE_IMAGE_FORMAT) @@ -464,12 +466,10 @@ function configure_glance { # will attempt the uwsgi binary instead. iniset $GLANCE_API_CONF wsgi python_interpreter $PYTHON - if [[ "$GLANCE_ENFORCE_SCOPE" == True || "$ENFORCE_SCOPE" == True ]] ; then - iniset $GLANCE_API_CONF oslo_policy enforce_scope true + if [[ "$GLANCE_ENFORCE_NEW_DEFAULTS" == True || "$ENFORCE_NEW_DEFAULTS" == True ]] ; then iniset $GLANCE_API_CONF oslo_policy enforce_new_defaults true iniset $GLANCE_API_CONF DEFAULT enforce_secure_rbac true else - iniset $GLANCE_API_CONF oslo_policy enforce_scope false iniset $GLANCE_API_CONF oslo_policy enforce_new_defaults false iniset $GLANCE_API_CONF DEFAULT enforce_secure_rbac false fi diff --git a/lib/keystone b/lib/keystone index 791abeb0d7..6e9be537a5 100644 --- a/lib/keystone +++ b/lib/keystone @@ -113,11 +113,13 @@ KEYSTONE_ENABLE_CACHE=${KEYSTONE_ENABLE_CACHE:-True} # Whether to create a keystone admin endpoint for legacy applications KEYSTONE_ADMIN_ENDPOINT=$(trueorfalse False KEYSTONE_ADMIN_ENDPOINT) -# Flag to set the oslo_policy.enforce_scope. This is used to switch -# the Identity API policies to start checking the scope of token. By Default, -# this flag is False. -# For more detail: https://docs.openstack.org/oslo.policy/latest/configuration/index.html#oslo_policy.enforce_scope -KEYSTONE_ENFORCE_SCOPE=$(trueorfalse False KEYSTONE_ENFORCE_SCOPE) +# Flag to set the oslo_policy.enforce_new_defaults. This is used to switch +# the Identity API policies to use the new defaults. +# KEYSTONE_ENFORCE_SCOPE is a deprecated alias for KEYSTONE_ENFORCE_NEW_DEFAULTS. +KEYSTONE_ENFORCE_NEW_DEFAULTS=$(trueorfalse False KEYSTONE_ENFORCE_NEW_DEFAULTS) +if [[ -n "${KEYSTONE_ENFORCE_SCOPE}" ]]; then + KEYSTONE_ENFORCE_NEW_DEFAULTS=$(trueorfalse False KEYSTONE_ENFORCE_SCOPE) +fi # Functions # --------- @@ -211,11 +213,9 @@ function configure_keystone { iniset $KEYSTONE_CONF oslo_policy policy_file policy.yaml - if [[ "$KEYSTONE_ENFORCE_SCOPE" == True || "$ENFORCE_SCOPE" == True ]] ; then - iniset $KEYSTONE_CONF oslo_policy enforce_scope true + if [[ "$KEYSTONE_ENFORCE_NEW_DEFAULTS" == True || "$ENFORCE_NEW_DEFAULTS" == True ]] ; then iniset $KEYSTONE_CONF oslo_policy enforce_new_defaults true else - iniset $KEYSTONE_CONF oslo_policy enforce_scope false iniset $KEYSTONE_CONF oslo_policy enforce_new_defaults false fi } diff --git a/lib/neutron b/lib/neutron index 6a7f057ad7..48260fccb4 100644 --- a/lib/neutron +++ b/lib/neutron @@ -82,11 +82,14 @@ export NEUTRON_TEST_CONFIG_FILE=${NEUTRON_TEST_CONFIG_FILE:-"$NEUTRON_CONF_DIR/d NEUTRON_UWSGI=neutron.wsgi.api:application NEUTRON_UWSGI_CONF=$NEUTRON_CONF_DIR/neutron-api-uwsgi.ini -# If NEUTRON_ENFORCE_SCOPE == True, it will set "enforce_scope" -# and "enforce_new_defaults" to True in the Neutron's config to enforce usage -# of the new RBAC policies and scopes. Set it to False if you do not -# want to run Neutron with new RBAC. -NEUTRON_ENFORCE_SCOPE=$(trueorfalse True NEUTRON_ENFORCE_SCOPE) +# If NEUTRON_ENFORCE_NEW_DEFAULTS == True, it will set "enforce_new_defaults" +# to True in the Neutron's config to enforce usage of the new RBAC policies. +# Set it to False if you do not want to run Neutron with new RBAC. +# NEUTRON_ENFORCE_SCOPE is a deprecated alias for NEUTRON_ENFORCE_NEW_DEFAULTS. +NEUTRON_ENFORCE_NEW_DEFAULTS=$(trueorfalse True NEUTRON_ENFORCE_NEW_DEFAULTS) +if [[ -n "${NEUTRON_ENFORCE_SCOPE}" ]]; then + NEUTRON_ENFORCE_NEW_DEFAULTS=$(trueorfalse True NEUTRON_ENFORCE_SCOPE) +fi # Agent binaries. Note, binary paths for other agents are set in per-service # scripts in lib/neutron_plugins/services/ @@ -559,14 +562,12 @@ function configure_neutron_after_post_config { } # configure_rbac_policies() - Configure Neutron to enforce new RBAC -# policies and scopes if NEUTRON_ENFORCE_SCOPE == True +# policies and scopes if NEUTRON_ENFORCE_NEW_DEFAULTS == True function configure_rbac_policies { - if [[ "$NEUTRON_ENFORCE_SCOPE" == "True" || "$ENFORCE_SCOPE" == True ]]; then + if [[ "$NEUTRON_ENFORCE_NEW_DEFAULTS" == "True" || "$ENFORCE_NEW_DEFAULTS" == True ]]; then iniset $NEUTRON_CONF oslo_policy enforce_new_defaults True - iniset $NEUTRON_CONF oslo_policy enforce_scope True else iniset $NEUTRON_CONF oslo_policy enforce_new_defaults False - iniset $NEUTRON_CONF oslo_policy enforce_scope False fi } diff --git a/lib/nova b/lib/nova index dcb4f46935..1e270fb20f 100644 --- a/lib/nova +++ b/lib/nova @@ -102,11 +102,16 @@ NOVA_SERVICE_LISTEN_ADDRESS=${NOVA_SERVICE_LISTEN_ADDRESS:-$(ipv6_unquote $SERVI METADATA_SERVICE_PORT=${METADATA_SERVICE_PORT:-8775} NOVA_ENABLE_CACHE=${NOVA_ENABLE_CACHE:-True} -# Flag to set the oslo_policy.enforce_scope and oslo_policy.enforce_new_defaults. -# This is used to disable the compute API policies scope and new defaults. +# Flag to set the oslo_policy.enforce_new_defaults. +# This is used to disable the compute API policies new defaults. # By Default, it is True. -# For more detail: https://docs.openstack.org/oslo.policy/latest/configuration/index.html#oslo_policy.enforce_scope -NOVA_ENFORCE_SCOPE=$(trueorfalse True NOVA_ENFORCE_SCOPE) +# For more detail: https://docs.openstack.org/oslo.policy/latest/configuration/index.html#oslo_policy.enforce_new_defaults +# NOVA_ENFORCE_SCOPE is a deprecated alias for NOVA_ENFORCE_NEW_DEFAULTS. +NOVA_ENFORCE_NEW_DEFAULTS=$(trueorfalse True NOVA_ENFORCE_NEW_DEFAULTS) +# Support the deprecated NOVA_ENFORCE_SCOPE variable as a fallback. +if [[ -n "${NOVA_ENFORCE_SCOPE}" ]]; then + NOVA_ENFORCE_NEW_DEFAULTS=$(trueorfalse True NOVA_ENFORCE_SCOPE) +fi if [[ $SERVICE_IP_VERSION == 6 ]]; then NOVA_MY_IP="$HOST_IPV6" @@ -501,12 +506,10 @@ function create_nova_conf { NOVA_ENABLED_APIS=$(echo $NOVA_ENABLED_APIS | sed "s/,metadata//") fi iniset $NOVA_CONF DEFAULT enabled_apis "$NOVA_ENABLED_APIS" - if [[ "$NOVA_ENFORCE_SCOPE" == "True" || "$ENFORCE_SCOPE" == "True" ]]; then + if [[ "$NOVA_ENFORCE_NEW_DEFAULTS" == "True" || "$ENFORCE_NEW_DEFAULTS" == "True" ]]; then iniset $NOVA_CONF oslo_policy enforce_new_defaults True - iniset $NOVA_CONF oslo_policy enforce_scope True else iniset $NOVA_CONF oslo_policy enforce_new_defaults False - iniset $NOVA_CONF oslo_policy enforce_scope False fi configure_keystone_authtoken_middleware $NOVA_CONF nova diff --git a/lib/placement b/lib/placement index 03aaa0344b..f9682dc58b 100644 --- a/lib/placement +++ b/lib/placement @@ -48,11 +48,13 @@ fi PLACEMENT_SERVICE_PROTOCOL=${PLACEMENT_SERVICE_PROTOCOL:-$SERVICE_PROTOCOL} PLACEMENT_SERVICE_HOST=${PLACEMENT_SERVICE_HOST:-$SERVICE_HOST} -# Flag to set the oslo_policy.enforce_scope and oslo_policy.enforce_new_defaults. -# This is used to switch the Placement API policies scope and new defaults. -# By Default, these flag are False. -# For more detail: https://docs.openstack.org/oslo.policy/latest/configuration/index.html#oslo_policy.enforce_scope -PLACEMENT_ENFORCE_SCOPE=$(trueorfalse False PLACEMENT_ENFORCE_SCOPE) +# Flag to set the oslo_policy.enforce_new_defaults. +# This is used to switch the Placement API policies to the new defaults. +# PLACEMENT_ENFORCE_SCOPE is a deprecated alias for PLACEMENT_ENFORCE_NEW_DEFAULTS. +PLACEMENT_ENFORCE_NEW_DEFAULTS=$(trueorfalse False PLACEMENT_ENFORCE_NEW_DEFAULTS) +if [[ -n "${PLACEMENT_ENFORCE_SCOPE}" ]]; then + PLACEMENT_ENFORCE_NEW_DEFAULTS=$(trueorfalse False PLACEMENT_ENFORCE_SCOPE) +fi # Functions # --------- @@ -87,12 +89,10 @@ function configure_placement { create_placement_conf write_uwsgi_config "$PLACEMENT_UWSGI_CONF" "$PLACEMENT_UWSGI" "/placement" "" "placement-api" - if [[ "$PLACEMENT_ENFORCE_SCOPE" == "True" || "$ENFORCE_SCOPE" == "True" ]]; then + if [[ "$PLACEMENT_ENFORCE_NEW_DEFAULTS" == "True" || "$ENFORCE_NEW_DEFAULTS" == "True" ]]; then iniset $PLACEMENT_CONF oslo_policy enforce_new_defaults True - iniset $PLACEMENT_CONF oslo_policy enforce_scope True else iniset $PLACEMENT_CONF oslo_policy enforce_new_defaults False - iniset $PLACEMENT_CONF oslo_policy enforce_scope False fi } diff --git a/lib/tempest b/lib/tempest index 1ebe9c5f1f..9546b4e5f6 100644 --- a/lib/tempest +++ b/lib/tempest @@ -547,7 +547,7 @@ function configure_tempest { iniset $TEMPEST_CONFIG network-feature-enabled ipv6_subnet_attributes "$IPV6_SUBNET_ATTRIBUTES_ENABLED" iniset $TEMPEST_CONFIG network-feature-enabled port_security $NEUTRON_PORT_SECURITY - iniset $TEMPEST_CONFIG enforce_scope neutron "$NEUTRON_ENFORCE_SCOPE" + iniset $TEMPEST_CONFIG enforce_scope neutron "$NEUTRON_ENFORCE_NEW_DEFAULTS" # Scenario SCENARIO_IMAGE_DIR=${SCENARIO_IMAGE_DIR:-$FILES} @@ -729,23 +729,23 @@ function configure_tempest { # If services enable the enforce_scope for their policy # we need to enable the same on Tempest side so that # test can be run with scoped token. - if [[ "$KEYSTONE_ENFORCE_SCOPE" == True || "$ENFORCE_SCOPE" == True ]] ; then + if [[ "$KEYSTONE_ENFORCE_NEW_DEFAULTS" == True || "$ENFORCE_NEW_DEFAULTS" == True ]] ; then iniset $TEMPEST_CONFIG enforce_scope keystone true fi - if [[ "$NOVA_ENFORCE_SCOPE" == True || "$ENFORCE_SCOPE" == True ]] ; then + if [[ "$NOVA_ENFORCE_NEW_DEFAULTS" == True || "$ENFORCE_NEW_DEFAULTS" == True ]] ; then iniset $TEMPEST_CONFIG enforce_scope nova true fi - if [[ "$PLACEMENT_ENFORCE_SCOPE" == True || "$ENFORCE_SCOPE" == True ]] ; then + if [[ "$PLACEMENT_ENFORCE_NEW_DEFAULTS" == True || "$ENFORCE_NEW_DEFAULTS" == True ]] ; then iniset $TEMPEST_CONFIG enforce_scope placement true fi - if [[ "$GLANCE_ENFORCE_SCOPE" == True || "$ENFORCE_SCOPE" == True ]] ; then + if [[ "$GLANCE_ENFORCE_NEW_DEFAULTS" == True || "$ENFORCE_NEW_DEFAULTS" == True ]] ; then iniset $TEMPEST_CONFIG enforce_scope glance true fi - if [[ "$CINDER_ENFORCE_SCOPE" == True || "$ENFORCE_SCOPE" == True ]] ; then + if [[ "$CINDER_ENFORCE_NEW_DEFAULTS" == True || "$ENFORCE_NEW_DEFAULTS" == True ]] ; then iniset $TEMPEST_CONFIG enforce_scope cinder true fi diff --git a/stackrc b/stackrc index ac9b7ee8ce..ad0cbaf75e 100644 --- a/stackrc +++ b/stackrc @@ -162,9 +162,13 @@ else export PS4='+ $(short_source): ' fi -# Global option for enforcing scope. If enabled, ENFORCE_SCOPE overrides -# each services ${SERVICE}_ENFORCE_SCOPE variables -ENFORCE_SCOPE=$(trueorfalse False ENFORCE_SCOPE) +# Global option for enforcing new defaults. If enabled, ENFORCE_NEW_DEFAULTS +# overrides each services ${SERVICE}_ENFORCE_SCOPE variables. +# ENFORCE_SCOPE is a deprecated alias for ENFORCE_NEW_DEFAULTS. +ENFORCE_NEW_DEFAULTS=$(trueorfalse False ENFORCE_NEW_DEFAULTS) +if [[ -n "${ENFORCE_SCOPE}" ]]; then + ENFORCE_NEW_DEFAULTS=$(trueorfalse False ENFORCE_SCOPE) +fi # Devstack supports the use of a global virtualenv. These variables enable # and disable this functionality as well as set the path to the virtualenv. From b3e41d0209e0aa93403b0d16c6afb1510ff2444e Mon Sep 17 00:00:00 2001 From: Sean Mooney Date: Wed, 13 May 2026 15:04:53 +0000 Subject: [PATCH 03/15] Add Ubuntu 26.04 platform support Ubuntu 26.04 (resolute) is the next Ubuntu LTS target for DevStack platform coverage. Add it to the supported distro list and define a non-voting resolute platform job so it can be exercised in check and periodic queues. Resolute uses sudo-rs, which does not support requiretty, and exposes some optional kernel tunables differently. Detect sudo-rs before writing sudoers options, make optional sysfs and sysctl tuning best-effort, and use the C locale for OVN extension sorting to keep setup portable. Disable the noVNC proxy in the resolute platform job until Nova's Python 3.14 noVNC compatibility fix is available. Depends-On: https://review.opendev.org/c/openstack/keystone/+/992782 Assisted-By: pi gpt-5.5 Change-Id: I48518a67f06e2e875bb2fc2034e1517a7e0164b0 Signed-off-by: Sean Mooney --- .zuul.yaml | 26 +++++++++++++++ functions-common | 6 ++++ lib/host | 59 ++++++++++++++++++++++++++--------- lib/neutron_plugins/ovn_agent | 8 ++--- stack.sh | 7 +++-- 5 files changed, 85 insertions(+), 21 deletions(-) diff --git a/.zuul.yaml b/.zuul.yaml index a37520d93f..a969440c84 100644 --- a/.zuul.yaml +++ b/.zuul.yaml @@ -18,6 +18,16 @@ nodes: - controller +- nodeset: + name: openstack-single-node-resolute + nodes: + - name: controller + label: ubuntu-resolute-8GB + groups: + - name: tempest + nodes: + - controller + - nodeset: name: openstack-single-node-focal nodes: @@ -841,6 +851,20 @@ vars: configure_swap_size: 4096 +- job: + name: devstack-platform-ubuntu-resolute + parent: tempest-full-py3 + description: Ubuntu 26.04 LTS (resolute) platform test + nodeset: openstack-single-node-resolute + voting: false + timeout: 9000 + vars: + configure_swap_size: 8192 + devstack_services: + n-novnc: false + devstack_localrc: + NOVA_VNC_ENABLED: false + - job: name: devstack-platform-ubuntu-noble-ovn-source parent: tempest-full-py3 @@ -988,6 +1012,7 @@ - devstack-platform-rocky-red-quartz - devstack-platform-ubuntu-noble-ovn-source - devstack-platform-ubuntu-noble-ovs + - devstack-platform-ubuntu-resolute - devstack-multinode - devstack-unit-tests - openstack-tox-bashate @@ -1073,3 +1098,4 @@ - devstack-platform-rocky-red-quartz - devstack-platform-ubuntu-noble-ovn-source - devstack-platform-ubuntu-noble-ovs + - devstack-platform-ubuntu-resolute diff --git a/functions-common b/functions-common index b3a4b57f01..62746afc98 100644 --- a/functions-common +++ b/functions-common @@ -557,6 +557,12 @@ function is_openeuler { fi [ "$os_VENDOR" = "openEuler" ] } + +# Determine if the sudo implementation is sudo-rs +# is_sudo_rs +function is_sudo_rs { + sudo --version 2>/dev/null | grep -q '^sudo-rs ' +} # Git Functions # ============= diff --git a/lib/host b/lib/host index 58062eff6b..51484e9add 100644 --- a/lib/host +++ b/lib/host @@ -11,13 +11,35 @@ # to opt out if the CPU time is more important to them. ENABLE_KSM=$(trueorfalse True ENABLE_KSM) ENABLE_KSMTUNED=$(trueorfalse True ENABLE_KSMTUNED) +function set_sysfs_parameter { + local name=$1 + local value=$2 + local param_file=$3 + + if [[ ! -e $param_file ]]; then + echo "WARNING: ${name} parameter ${param_file} is not present, skipping" + return 0 + fi + + if ! echo ${value} | sudo tee ${param_file}; then + echo "WARNING: failed to set ${name} parameter ${param_file}=${value}, continuing" + fi +} + +function set_sysctl_parameter { + local name=$1 + local value=$2 + + if ! sudo sysctl -w ${name}=${value}; then + echo "WARNING: failed to set sysctl parameter ${name}=${value}, continuing" + fi +} + function configure_ksm { if [[ $ENABLE_KSMTUNED == "True" ]] ; then install_package "ksmtuned" fi - if [[ -f /sys/kernel/mm/ksm/run ]] ; then - echo $(bool_to_int ENABLE_KSM) | sudo tee /sys/kernel/mm/ksm/run - fi + set_sysfs_parameter ksm $(bool_to_int ENABLE_KSM) /sys/kernel/mm/ksm/run } # Compressed swap (ZSWAP) @@ -36,15 +58,22 @@ ENABLE_ZSWAP=$(trueorfalse False ENABLE_ZSWAP) # zstd has much better compression but more latency ZSWAP_COMPRESSOR=${ZSWAP_COMPRESSOR:="lz4"} ZSWAP_ZPOOL=${ZSWAP_ZPOOL:="zsmalloc"} +function set_zswap_parameter { + local name=$1 + local value=$2 + + set_sysfs_parameter zswap ${value} /sys/module/zswap/parameters/${name} +} + function configure_zswap { if [[ $ENABLE_ZSWAP == "True" ]] ; then # Centos 9 stream seems to only support enabling but not run time # tuning so dont try to choose better default on centos if is_ubuntu; then - echo ${ZSWAP_COMPRESSOR} | sudo tee /sys/module/zswap/parameters/compressor - echo ${ZSWAP_ZPOOL} | sudo tee /sys/module/zswap/parameters/zpool + set_zswap_parameter compressor ${ZSWAP_COMPRESSOR} + set_zswap_parameter zpool ${ZSWAP_ZPOOL} fi - echo 1 | sudo tee /sys/module/zswap/parameters/enabled + set_zswap_parameter enabled 1 # print curent zswap kernel config sudo grep -R . /sys/module/zswap/parameters || /bin/true fi @@ -54,14 +83,14 @@ ENABLE_SYSCTL_MEM_TUNING=$(trueorfalse False ENABLE_SYSCTL_MEM_TUNING) function configure_sysctl_mem_parmaters { if [[ $ENABLE_SYSCTL_MEM_TUNING == "True" ]] ; then # defer write when memory is available - sudo sysctl -w vm.dirty_ratio=60 - sudo sysctl -w vm.dirty_background_ratio=10 - sudo sysctl -w vm.vfs_cache_pressure=50 + set_sysctl_parameter vm.dirty_ratio 60 + set_sysctl_parameter vm.dirty_background_ratio 10 + set_sysctl_parameter vm.vfs_cache_pressure 50 # assume swap is compressed so on new kernels # give it equal priority as page cache which is # uncompressed. on kernels < 5.8 the max is 100 # not 200 so it will strongly prefer swapping. - sudo sysctl -w vm.swappiness=100 + set_sysctl_parameter vm.swappiness 100 sudo grep -R . /proc/sys/vm/ || /bin/true fi } @@ -76,15 +105,15 @@ ENABLE_SYSCTL_NET_TUNING=$(trueorfalse False ENABLE_SYSCTL_NET_TUNING) function configure_sysctl_net_parmaters { if [[ $ENABLE_SYSCTL_NET_TUNING == "True" ]] ; then # detect dead TCP connections after 120 seconds - sudo sysctl -w net.ipv4.tcp_keepalive_time=60 - sudo sysctl -w net.ipv4.tcp_keepalive_intvl=10 - sudo sysctl -w net.ipv4.tcp_keepalive_probes=6 + set_sysctl_parameter net.ipv4.tcp_keepalive_time 60 + set_sysctl_parameter net.ipv4.tcp_keepalive_intvl 10 + set_sysctl_parameter net.ipv4.tcp_keepalive_probes 6 # reudce network latency for new connections - sudo sysctl -w net.ipv4.tcp_fastopen=3 + set_sysctl_parameter net.ipv4.tcp_fastopen 3 # print tcp options sudo grep -R . /proc/sys/net/ipv4/tcp* || /bin/true # disable qos by default - sudo sysctl -w net.core.default_qdisc=pfifo_fast + set_sysctl_parameter net.core.default_qdisc pfifo_fast fi } diff --git a/lib/neutron_plugins/ovn_agent b/lib/neutron_plugins/ovn_agent index 01bbe35997..a5e58f964d 100644 --- a/lib/neutron_plugins/ovn_agent +++ b/lib/neutron_plugins/ovn_agent @@ -475,10 +475,10 @@ function filter_network_api_extensions { SUPPORTED_NETWORK_API_EXTENSIONS="$SUPPORTED_NETWORK_API_EXTENSIONS,qos" fi NETWORK_API_EXTENSIONS=${NETWORK_API_EXTENSIONS:-$SUPPORTED_NETWORK_API_EXTENSIONS} - extensions=$(echo $NETWORK_API_EXTENSIONS | tr ', ' '\n' | sort -u) - supported_ext=$(echo $SUPPORTED_NETWORK_API_EXTENSIONS | tr ', ' '\n' | sort -u) - enabled_ext=$(comm -12 <(echo -e "$extensions") <(echo -e "$supported_ext")) - disabled_ext=$(comm -3 <(echo -e "$extensions") <(echo -e "$enabled_ext")) + extensions=$(echo $NETWORK_API_EXTENSIONS | tr ', ' '\n' | LC_ALL=C sort -u) + supported_ext=$(echo $SUPPORTED_NETWORK_API_EXTENSIONS | tr ', ' '\n' | LC_ALL=C sort -u) + enabled_ext=$(LC_ALL=C comm -12 <(echo -e "$extensions") <(echo -e "$supported_ext")) + disabled_ext=$(LC_ALL=C comm -3 <(echo -e "$extensions") <(echo -e "$enabled_ext")) # Log a message in case some extensions had to be disabled because # they are not supported by the OVN driver diff --git a/stack.sh b/stack.sh index c6d37611c9..a36d73cec5 100755 --- a/stack.sh +++ b/stack.sh @@ -229,7 +229,7 @@ write_devstack_version # Warn users who aren't on an explicitly supported distro, but allow them to # override check and attempt installation with ``FORCE=yes ./stack`` -SUPPORTED_DISTROS="trixie|bookworm|noble|rhel9|rhel10" +SUPPORTED_DISTROS="trixie|bookworm|noble|resolute|rhel9|rhel10" if [[ ! ${DISTRO} =~ $SUPPORTED_DISTROS ]]; then echo "WARNING: this script has not been tested on $DISTRO" @@ -275,7 +275,10 @@ echo "$STACK_USER ALL=(root) NOPASSWD:ALL" >$TEMPFILE # Some binaries might be under ``/sbin`` or ``/usr/sbin``, so make sure sudo will # see them by forcing ``PATH`` echo "Defaults:$STACK_USER secure_path=/sbin:/usr/sbin:/usr/bin:/bin:/usr/local/sbin:/usr/local/bin" >> $TEMPFILE -echo "Defaults:$STACK_USER !requiretty" >> $TEMPFILE +# sudo-rs does not support the requiretty option. +if ! is_sudo_rs; then + echo "Defaults:$STACK_USER !requiretty" >> $TEMPFILE +fi chmod 0440 $TEMPFILE sudo chown root:root $TEMPFILE sudo mv $TEMPFILE /etc/sudoers.d/50_stack_sh From 6362aa0c5f1180e9c9349609d4f98043a9f1f67d Mon Sep 17 00:00:00 2001 From: Sean Mooney Date: Fri, 12 Jun 2026 09:57:16 +0100 Subject: [PATCH 04/15] Re-enable resolute noVNC proxy Nova has fixed Python 3.14 noVNC incompatibility, so the resolute platform job can exercise the default noVNC deployment again Depends-On: https://review.opendev.org/c/openstack/nova/+/987815 Change-Id: I5892db8e51fc01793a50d904dcd132312f30b4d3 Signed-off-by: Sean Mooney --- .zuul.yaml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/.zuul.yaml b/.zuul.yaml index a969440c84..826de3262a 100644 --- a/.zuul.yaml +++ b/.zuul.yaml @@ -860,10 +860,6 @@ timeout: 9000 vars: configure_swap_size: 8192 - devstack_services: - n-novnc: false - devstack_localrc: - NOVA_VNC_ENABLED: false - job: name: devstack-platform-ubuntu-noble-ovn-source From 886291296c846797d58396bd45cd8a5cbbb1775e Mon Sep 17 00:00:00 2001 From: Sean Mooney Date: Wed, 17 Jun 2026 21:51:09 +0100 Subject: [PATCH 05/15] Run resolute noVNC proxy in threaded mode Configure the resolute platform job to run n-novnc-cell1 with OS_NOVA_DISABLE_EVENTLET_PATCHING=true. This keeps noVNC enabled with explicit threaded-mode coverage in advance of nova's default change. Change-Id: I314c001ab01767c1fb281a853135c5d13f653189 Signed-off-by: Sean Mooney --- .zuul.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.zuul.yaml b/.zuul.yaml index 826de3262a..7776e5b803 100644 --- a/.zuul.yaml +++ b/.zuul.yaml @@ -860,6 +860,8 @@ timeout: 9000 vars: configure_swap_size: 8192 + devstack_localrc: + 'SYSTEMD_ENV_VARS["n-novnc-cell1"]': OS_NOVA_DISABLE_EVENTLET_PATCHING=true - job: name: devstack-platform-ubuntu-noble-ovn-source From 05f90d5d5c9d914bfc278276e3c2de50198cefd2 Mon Sep 17 00:00:00 2001 From: Ghanshyam Maan Date: Thu, 18 Jun 2026 00:31:45 +0000 Subject: [PATCH 06/15] Enforce new keystone policies by default MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The value of `KEYSTONE_ENFORCE_SCOPE` has been changed to `True` by default. This envrionment variable is used to set the values of `enforce_new_defaults` in the `[oslo_policy]` section of the keysonte configuration file. The default value for both oslo.policy options was changed to `True` in the Dalmatian (2024.2) cycle release. [1] But devstack continued to override this value by defaulting to `False`. With this change, keystone will use the same default as newer releases of oslo.policy. [1] https://docs.openstack.org/releasenotes/oslo.policy/2024.2.html Signed-off-by: Douglas Mendizábal Change-Id: I7edce1519db4fcb38f37082ddf1aa06d440c983b Signed-off-by: Ghanshyam Maan --- lib/keystone | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/keystone b/lib/keystone index 6e9be537a5..d26f68de5d 100644 --- a/lib/keystone +++ b/lib/keystone @@ -116,9 +116,9 @@ KEYSTONE_ADMIN_ENDPOINT=$(trueorfalse False KEYSTONE_ADMIN_ENDPOINT) # Flag to set the oslo_policy.enforce_new_defaults. This is used to switch # the Identity API policies to use the new defaults. # KEYSTONE_ENFORCE_SCOPE is a deprecated alias for KEYSTONE_ENFORCE_NEW_DEFAULTS. -KEYSTONE_ENFORCE_NEW_DEFAULTS=$(trueorfalse False KEYSTONE_ENFORCE_NEW_DEFAULTS) +KEYSTONE_ENFORCE_NEW_DEFAULTS=$(trueorfalse True KEYSTONE_ENFORCE_NEW_DEFAULTS) if [[ -n "${KEYSTONE_ENFORCE_SCOPE}" ]]; then - KEYSTONE_ENFORCE_NEW_DEFAULTS=$(trueorfalse False KEYSTONE_ENFORCE_SCOPE) + KEYSTONE_ENFORCE_NEW_DEFAULTS=$(trueorfalse True KEYSTONE_ENFORCE_SCOPE) fi # Functions From bc0a2651c3255c84d8b11777cb4890f43a96e70c Mon Sep 17 00:00:00 2001 From: Masayoshi Mizuma Date: Tue, 7 Apr 2026 08:39:08 +0900 Subject: [PATCH 07/15] Ensure wget is installed before use in _install_rdo In RHEL-based environments, the _install_rdo function uses wget to fetch the delorean-deps repository file. However, wget might not be present in a minimal OS installation (e.g., CentOS Stream 10 Cloud images), which causes the download to fail and subsequent tasks like rabbitmq-server installation to break. This patch adds a check to ensure wget is installed using the is_package_installed and install_package helper functions before attempting to download the repository file. Change-Id: I3e99096e2892c2b1bf04e618aa521d665790d27d Signed-off-by: Masayoshi Mizuma --- stack.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/stack.sh b/stack.sh index c6d37611c9..42af8eca8b 100755 --- a/stack.sh +++ b/stack.sh @@ -304,6 +304,9 @@ function _install_rdo { if [[ $DISTRO =~ "rhel" ]]; then VERSION=${DISTRO:4:2} rdo_release=${TARGET_BRANCH#*/} + + install_package wget + if [[ "$TARGET_BRANCH" == "master" ]]; then # adding delorean-deps repo to provide current master rpms sudo wget https://trunk.rdoproject.org/centos${VERSION}-master/delorean-deps.repo -O /etc/yum.repos.d/delorean-deps.repo From 04fff27d0ad81fec4cbba2801b59203acf6f9919 Mon Sep 17 00:00:00 2001 From: Omer Date: Tue, 30 Jun 2026 17:28:30 +0200 Subject: [PATCH 08/15] Fix verify-ipv6-address.py crash on Python 3.14 The argparse help string contains "fe80::1%eth0" where "%e" is interpreted as a printf-style format specifier. Python 3.14 added eager validation of help strings at add_argument() time (cpython commit eb2d268ac7), causing the script to crash with "ValueError: badly formed help string" before it even parses the address. This potentially breaks all IPv6 Zuul jobs on Resolute nodes. Escape "%" as "%%" per the argparse documentation. Closes-Bug: #2158736 Change-Id: Ieda0388548d5964ec9dbc3cff52540a19e9f5625 Signed-off-by: Omer --- tools/verify-ipv6-address.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/verify-ipv6-address.py b/tools/verify-ipv6-address.py index dc18fa6d8a..29577672c0 100644 --- a/tools/verify-ipv6-address.py +++ b/tools/verify-ipv6-address.py @@ -17,7 +17,7 @@ def main(): " 2001:0db8:85a3:0000:0000:8a2e:0370:7334\n" " 2001:db8::1\n" " ::1\n" - " fe80::1%eth0 (scope IDs are handled)" + " fe80::1%%eth0 (scope IDs are handled)" ), ) args = parser.parse_args() From f3645feb8d5b79ced731bfa1a817743c67152aec Mon Sep 17 00:00:00 2001 From: Ghanshyam Maan Date: Tue, 30 Jun 2026 19:25:43 +0000 Subject: [PATCH 09/15] Enable SRBAC by default for all services We are in the process of changing the defaults in each service True and will eventually remove this option entirely. Until that happens, manually force it to True here and remove notes about defaults which are either already out of date or soon will be. Change-Id: Ifd965427dc92db8a590cc3e87e6d6691e11ba344 Signed-off-by: Stephen Finucane Signed-off-by: Ghanshyam Maan --- lib/cinder | 4 ++-- lib/nova | 1 - lib/placement | 4 ++-- stackrc | 4 ++-- 4 files changed, 6 insertions(+), 7 deletions(-) diff --git a/lib/cinder b/lib/cinder index 4510efe5e0..d8d31d300f 100644 --- a/lib/cinder +++ b/lib/cinder @@ -207,9 +207,9 @@ CINDER_UPLOAD_OPTIMIZED_BACKENDS=${CINDER_UPLOAD_OPTIMIZED_BACKENDS:-$CINDER_ENA # Flag to set the oslo_policy.enforce_new_defaults. This is used to switch # the Volume API policies to use the new defaults. # CINDER_ENFORCE_SCOPE is a deprecated alias for CINDER_ENFORCE_NEW_DEFAULTS. -CINDER_ENFORCE_NEW_DEFAULTS=$(trueorfalse False CINDER_ENFORCE_NEW_DEFAULTS) +CINDER_ENFORCE_NEW_DEFAULTS=$(trueorfalse True CINDER_ENFORCE_NEW_DEFAULTS) if [[ -n "${CINDER_ENFORCE_SCOPE}" ]]; then - CINDER_ENFORCE_NEW_DEFAULTS=$(trueorfalse False CINDER_ENFORCE_SCOPE) + CINDER_ENFORCE_NEW_DEFAULTS=$(trueorfalse True CINDER_ENFORCE_SCOPE) fi # Functions diff --git a/lib/nova b/lib/nova index 1e270fb20f..a02d745600 100644 --- a/lib/nova +++ b/lib/nova @@ -104,7 +104,6 @@ NOVA_ENABLE_CACHE=${NOVA_ENABLE_CACHE:-True} # Flag to set the oslo_policy.enforce_new_defaults. # This is used to disable the compute API policies new defaults. -# By Default, it is True. # For more detail: https://docs.openstack.org/oslo.policy/latest/configuration/index.html#oslo_policy.enforce_new_defaults # NOVA_ENFORCE_SCOPE is a deprecated alias for NOVA_ENFORCE_NEW_DEFAULTS. NOVA_ENFORCE_NEW_DEFAULTS=$(trueorfalse True NOVA_ENFORCE_NEW_DEFAULTS) diff --git a/lib/placement b/lib/placement index f9682dc58b..35cfb2e1bf 100644 --- a/lib/placement +++ b/lib/placement @@ -51,9 +51,9 @@ PLACEMENT_SERVICE_HOST=${PLACEMENT_SERVICE_HOST:-$SERVICE_HOST} # Flag to set the oslo_policy.enforce_new_defaults. # This is used to switch the Placement API policies to the new defaults. # PLACEMENT_ENFORCE_SCOPE is a deprecated alias for PLACEMENT_ENFORCE_NEW_DEFAULTS. -PLACEMENT_ENFORCE_NEW_DEFAULTS=$(trueorfalse False PLACEMENT_ENFORCE_NEW_DEFAULTS) +PLACEMENT_ENFORCE_NEW_DEFAULTS=$(trueorfalse True PLACEMENT_ENFORCE_NEW_DEFAULTS) if [[ -n "${PLACEMENT_ENFORCE_SCOPE}" ]]; then - PLACEMENT_ENFORCE_NEW_DEFAULTS=$(trueorfalse False PLACEMENT_ENFORCE_SCOPE) + PLACEMENT_ENFORCE_NEW_DEFAULTS=$(trueorfalse True PLACEMENT_ENFORCE_SCOPE) fi # Functions diff --git a/stackrc b/stackrc index ad0cbaf75e..24bdf9bc04 100644 --- a/stackrc +++ b/stackrc @@ -165,9 +165,9 @@ fi # Global option for enforcing new defaults. If enabled, ENFORCE_NEW_DEFAULTS # overrides each services ${SERVICE}_ENFORCE_SCOPE variables. # ENFORCE_SCOPE is a deprecated alias for ENFORCE_NEW_DEFAULTS. -ENFORCE_NEW_DEFAULTS=$(trueorfalse False ENFORCE_NEW_DEFAULTS) +ENFORCE_NEW_DEFAULTS=$(trueorfalse True ENFORCE_NEW_DEFAULTS) if [[ -n "${ENFORCE_SCOPE}" ]]; then - ENFORCE_NEW_DEFAULTS=$(trueorfalse False ENFORCE_SCOPE) + ENFORCE_NEW_DEFAULTS=$(trueorfalse True ENFORCE_SCOPE) fi # Devstack supports the use of a global virtualenv. These variables enable From 8a415cdb3cd50dd560029547abdf12ee18ad949f Mon Sep 17 00:00:00 2001 From: Simon Dodsley Date: Thu, 2 Jul 2026 10:00:59 -0400 Subject: [PATCH 10/15] Grant cinder service user the "member" role for barbican Cinder uses barbican (via castellan) to manage encryption keys for encrypted volumes. Some of these operations run as the cinder service user rather than as the end user -- notably the key transfer performed during an encrypted volume transfer, where transfer_create stores a new secret using the cinder service context. Barbican's legacy policy authorized secret creation via the "creator" role: secrets:post -> rule:admin_or_creator and devstack therefore grants the cinder service user the "creator" role when barbican is enabled. Barbican's new RBAC defaults instead require the "member" role: secrets:post -> True:%(enforce_new_defaults)s and role:member Now that enforce_scope / enforce_new_defaults are enabled by default, the cinder service user (which holds only "service" and "creator") is no longer permitted to create secrets, so every encrypted volume transfer fails with: Forbidden: Secret creation attempt not allowed - please review your user/project privileges oslo_policy.policy.PolicyNotAuthorized: secrets:post is disallowed by policy This breaks the cinder-tempest-plugin *-barbican jobs (TransferEncryptedVolumeTest.test_create_accept_volume_transfer) across all cinder changes. Additionally grant the cinder service user the "member" role in the service project when barbican is enabled. The existing "creator" grant is retained so the path keeps working under the deprecated policy as well. Change-Id: I1e902b77c73717a2c2b3a727a8f737e1f94193cf Signed-off-by: Simon Dodsley --- lib/cinder | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/lib/cinder b/lib/cinder index 4510efe5e0..bd722b7d6f 100644 --- a/lib/cinder +++ b/lib/cinder @@ -445,6 +445,7 @@ function configure_cinder { # ------------------------------------------------------------------ # SERVICE_PROJECT_NAME cinder service # SERVICE_PROJECT_NAME cinder creator (if Barbican is enabled) +# SERVICE_PROJECT_NAME cinder member (if Barbican is enabled) # Migrated from keystone_data.sh function create_cinder_accounts { @@ -453,13 +454,26 @@ function create_cinder_accounts { local extra_role="" - # cinder needs the "creator" role in order to interact with barbican + # cinder needs a barbican role in order to create secrets for + # encrypted volumes (for example the key transfer performed, as the + # cinder service user, during an encrypted volume transfer). + # Barbican's legacy policy authorized secret creation via the + # "creator" role (secrets:post -> rule:admin_or_creator); its new + # RBAC defaults require the "member" role (secrets:post -> + # role:member). Grant both so the encrypted-volume key path keeps + # working regardless of which policy barbican is enforcing. if is_service_enabled barbican; then extra_role=$(get_or_create_role "creator") fi create_service_user "cinder" $extra_role + if is_service_enabled barbican; then + get_or_add_user_project_role "member" "cinder" \ + "$SERVICE_PROJECT_NAME" "$SERVICE_DOMAIN_NAME" \ + "$SERVICE_DOMAIN_NAME" + fi + local cinder_api_url cinder_api_url="$CINDER_SERVICE_PROTOCOL://$CINDER_SERVICE_HOST/volume" From f1d1d8e04f5796e97d1f4c7bd8201d3e4eca2714 Mon Sep 17 00:00:00 2001 From: Eduardo Olivares Date: Tue, 23 Jun 2026 10:15:43 +0200 Subject: [PATCH 11/15] Add OVN agent EVPN configuration support When the ovn-evpn agent extension is enabled (q-ovn-evpn service), configure the [ovn_evpn] section in the OVN agent config file and set the required OVS external_ids for EVPN operation. New devstack variables: - OVN_EVPN_BGP_AS: BGP AS number for the EVPN extension - OVN_EVPN_BGP_LOCAL_INTERFACE: local interface for BGP peering - OVN_EVPN_VXLAN_PORT: VXLAN port for the SVD parent device (default 4789, sets ovn-evpn-vxlan-ports external_id) - OVN_EVPN_LOCAL_IP: local VTEP IP for EVPN (sets ovn-evpn-local-ip external_id) Also adds the evpn service plugin file, sourced from lib/neutron, which registers the "evpn" neutron service plugin class when the q-ovn-evpn service is enabled. Change-Id: I2c3ee1e6d576098f780cbd949702b06dea570a5b Signed-off-by: Eduardo Olivares Assisted-By: Claude Opus 4.6 --- lib/neutron | 4 ++++ lib/neutron_plugins/ovn_agent | 17 +++++++++++++++++ lib/neutron_plugins/services/evpn | 5 +++++ 3 files changed, 26 insertions(+) create mode 100644 lib/neutron_plugins/services/evpn diff --git a/lib/neutron b/lib/neutron index 48260fccb4..481ffc8449 100644 --- a/lib/neutron +++ b/lib/neutron @@ -283,6 +283,7 @@ source $TOP_DIR/lib/neutron_plugins/services/trunk source $TOP_DIR/lib/neutron_plugins/services/qos source $TOP_DIR/lib/neutron_plugins/services/segments source $TOP_DIR/lib/neutron_plugins/services/ovn-bgp +source $TOP_DIR/lib/neutron_plugins/services/evpn # Use security group or not if has_neutron_plugin_security_group; then @@ -429,6 +430,9 @@ function configure_neutron { if is_service_enabled q-ovn-bgp; then configure_ovn_bgp_service_plugin fi + if is_service_enabled q-ovn-evpn; then + configure_evpn_service_plugin + fi # Finally configure Neutron server and core plugin if is_service_enabled q-agt neutron-agent q-svc neutron-api; then diff --git a/lib/neutron_plugins/ovn_agent b/lib/neutron_plugins/ovn_agent index a5e58f964d..0d36930bd9 100644 --- a/lib/neutron_plugins/ovn_agent +++ b/lib/neutron_plugins/ovn_agent @@ -116,6 +116,12 @@ OVN_L3_CREATE_PUBLIC_NETWORK=$(trueorfalse True OVN_L3_CREATE_PUBLIC_NETWORK) # set to some non-empty value. NEUTRON_BGP_PEER_BRIDGES=${NEUTRON_BGP_PEER_BRIDGES:-} +# The following variables apply when OVN_AGENT_EXTENSIONS includes "ovn-evpn". +OVN_EVPN_BGP_AS=${OVN_EVPN_BGP_AS:-} +OVN_EVPN_BGP_LOCAL_INTERFACE=${OVN_EVPN_BGP_LOCAL_INTERFACE:-} +OVN_EVPN_VXLAN_PORT=${OVN_EVPN_VXLAN_PORT:-4789} +OVN_EVPN_LOCAL_IP=${OVN_EVPN_LOCAL_IP:-} + export OVSDB_SERVER_LOCAL_HOST=$SERVICE_LOCAL_HOST TUNNEL_IP=$TUNNEL_ENDPOINT_IP if [[ "$SERVICE_IP_VERSION" == 6 ]]; then @@ -612,6 +618,10 @@ function configure_ovn { if [[ $config_file == $OVN_AGENT_CONF ]]; then iniset $config_file agent extensions $OVN_AGENT_EXTENSIONS iniset $config_file ovn ovn_nb_connection $OVN_NB_REMOTE + if [[ "$OVN_AGENT_EXTENSIONS" =~ 'ovn-evpn' ]]; then + iniset $config_file ovn_evpn bgp_as $OVN_EVPN_BGP_AS + iniset $config_file ovn_evpn bgp_local_interface $OVN_EVPN_BGP_LOCAL_INTERFACE + fi fi fi } @@ -696,12 +706,19 @@ function _start_ovs { sudo ovs-vsctl --no-wait set open_vswitch . external-ids:ovn-cms-options="enable-chassis-as-gw" fi + # ovn-bgp and ovn-evpn extensions are not supported together so far if [[ "$OVN_AGENT_EXTENSIONS" =~ 'ovn-bgp' ]]; then if [[ -z "$NEUTRON_BGP_PEER_BRIDGES" ]]; then echo "NEUTRON_BGP_PEER_BRIDGES must be set when ovn-bgp extension is enabled" return 1 fi sudo ovs-vsctl --no-wait -- set Open_vSwitch . external-ids:neutron-bgp-peer-bridges=$NEUTRON_BGP_PEER_BRIDGES external-ids:neutron-bgp-interconnect-bridge=$OVS_PHYSICAL_BRIDGE + elif [[ "$OVN_AGENT_EXTENSIONS" =~ 'ovn-evpn' ]]; then + if [[ -z "$OVN_EVPN_LOCAL_IP" ]]; then + echo "OVN_EVPN_LOCAL_IP must be set when ovn-evpn extension is enabled" + return 1 + fi + sudo ovs-vsctl --no-wait -- set Open_vSwitch . external-ids:ovn-evpn-local-ip=$OVN_EVPN_LOCAL_IP external-ids:ovn-evpn-vxlan-ports=$OVN_EVPN_VXLAN_PORT elif is_provider_network || [[ $Q_USE_PROVIDERNET_FOR_PUBLIC == "True" ]]; then ovn_base_setup_bridge $OVS_PHYSICAL_BRIDGE sudo ovs-vsctl set open . external-ids:ovn-bridge-mappings=${PHYSICAL_NETWORK}:${OVS_PHYSICAL_BRIDGE} diff --git a/lib/neutron_plugins/services/evpn b/lib/neutron_plugins/services/evpn new file mode 100644 index 0000000000..2844a1fcb8 --- /dev/null +++ b/lib/neutron_plugins/services/evpn @@ -0,0 +1,5 @@ +#!/bin/bash + +function configure_evpn_service_plugin { + neutron_service_plugin_class_add "evpn" +} From 51eb2010d911091a9708e137d14cfcb23eaa2592 Mon Sep 17 00:00:00 2001 From: melanie witt Date: Wed, 15 Jul 2026 11:21:04 -0700 Subject: [PATCH 12/15] Collect Guru Meditation Reports on failed job runs Currently, Guru Meditation Reports (green thread stack dumps) are only collected when stack.sh itself fails, via the worlddump.py exit trap. When tempest tests fail due to a service hang (e.g. an eventlet green thread stuck in a privsep RPC call), no GMR is captured and the only way to diagnose the hang is indirect evidence from libvirtd logs, process trees, and LVM metadata. Add a post-run task that sends SIGUSR2 to OpenStack services on failed job runs, triggering their GMR handlers. The task runs before export-devstack-journal so the thread dumps appear in the collected service logs. SIGUSR2 does not terminate the processes. Assisted-by: Claude claude-opus-4-6 2.1.210 Change-Id: I55487cf774c43523fe60f703e2abb170f376803b Signed-off-by: melanie witt --- playbooks/post.yaml | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/playbooks/post.yaml b/playbooks/post.yaml index 0047d78ea5..27c9ef9934 100644 --- a/playbooks/post.yaml +++ b/playbooks/post.yaml @@ -23,6 +23,36 @@ cmd: | coredumpctl -o {{ devstack_log_dir }}/qemu.coredump dump /usr/bin/qemu-system-x86_64 ignore_errors: yes + # This must run before export-devstack-journal so the reports + # appear in the collected service logs. + - name: Collect Guru Meditation Reports from OpenStack services + shell: + executable: /bin/bash + cmd: | + # Send SIGUSR2 to trigger Guru Meditation Reports (green + # thread stack dumps) from OpenStack services so that hangs + # during test runs are diagnosable from the collected + # service logs. The signal does not terminate the processes. + # Matches GMR_PROCESSES in tools/worlddump.py + gmr_services=( + nova-compute + neutron-dhcp-agent + neutron-l3-agent + neutron-metadata-agent + neutron-openvswitch-agent + cinder-volume + ) + # Use pkill -f (not killall -e as worlddump.py does) + # because the process name is python3, not the service name. + for service in "${gmr_services[@]}"; do + if pgrep -f "$service" > /dev/null 2>&1; then + pkill -USR2 -f "$service" || true + fi + done + # Allow time for reports to be written to journald + sleep 2 + when: not (zuul_success | bool) + ignore_errors: yes roles: - export-devstack-journal - apache-logs-conf From 79677ddab6275012e1782325a04c20d6497a1d52 Mon Sep 17 00:00:00 2001 From: Rodolfo Alonso Hernandez Date: Thu, 23 Jul 2026 09:45:15 +0200 Subject: [PATCH 13/15] ovs: Remove OVS kernel module build support OVS dropped support for building out-of-tree kernel modules after kernel 5.5. All currently supported distros ship kernels well above that version, so ``OVN_BUILD_MODULES`` and the ``build_modules`` parameter in ``compile_ovs`` / ``prepare_for_ovs_compilation`` are dead code. Remove ``OVN_BUILD_MODULES`` from ``ovn_agent``, strip the ``build_modules`` parameter and all its conditionals from ``compile_ovs`` and ``prepare_for_ovs_compilation`` (kernel version guard, ``--with-linux`` configure flag, ``modules_install`` target, and kernel header package installation). Closes-Bug: #2161600 Assisted-By: Claude Opus 4.6 Signed-off-by: Rodolfo Alonso Hernandez Change-Id: Ic3d3fc6e2016af6c191ea35eef081b0dec41621a --- lib/neutron_plugins/ovn_agent | 5 +-- lib/neutron_plugins/ovs_source | 71 ++++------------------------------ 2 files changed, 8 insertions(+), 68 deletions(-) diff --git a/lib/neutron_plugins/ovn_agent b/lib/neutron_plugins/ovn_agent index 0d36930bd9..edd3568d93 100644 --- a/lib/neutron_plugins/ovn_agent +++ b/lib/neutron_plugins/ovn_agent @@ -65,9 +65,6 @@ OVN_L3_SCHEDULER=${OVN_L3_SCHEDULER:-leastloaded} # Open vSwitch service. OVN_UUID=${OVN_UUID:-} -# Whether or not to build the openvswitch kernel module from ovs. This is required -# unless the distro kernel includes ovs+conntrack support. -OVN_BUILD_MODULES=$(trueorfalse False OVN_BUILD_MODULES) OVN_BUILD_FROM_SOURCE=$(trueorfalse False OVN_BUILD_FROM_SOURCE) if [[ "$OVN_BUILD_FROM_SOURCE" == "True" ]]; then Q_BUILD_OVS_FROM_GIT=True @@ -427,7 +424,7 @@ function install_ovn { remove_ovs_packages sudo rm -f $OVS_RUNDIR/* - compile_ovs $OVN_BUILD_MODULES + compile_ovs if use_new_ovn_repository; then compile_ovn fi diff --git a/lib/neutron_plugins/ovs_source b/lib/neutron_plugins/ovs_source index 6b6f531a01..feb8f0acd0 100644 --- a/lib/neutron_plugins/ovs_source +++ b/lib/neutron_plugins/ovs_source @@ -42,7 +42,6 @@ function load_module { # prepare_for_compilation() - Fetch ovs git repository and install packages needed for # compilation. function prepare_for_ovs_compilation { - local build_modules=${1:-False} OVS_DIR=$DEST/$OVS_REPO_NAME if [ ! -d $OVS_DIR ] ; then @@ -59,44 +58,6 @@ function prepare_for_ovs_compilation { # TODO: Can you create package list files like you can inside devstack? install_package autoconf automake libtool gcc patch make - - # If build_modules is False, we don't need to install the kernel-* - # packages. Just return. - if [[ "$build_modules" == "False" ]]; then - return - fi - - KERNEL_VERSION=`uname -r` - if is_fedora ; then - # is_fedora covers Fedora, RHEL, CentOS, etc... - if [[ "$os_VENDOR" == "Fedora" ]]; then - install_package elfutils-libelf-devel - KERNEL_VERSION=`echo $KERNEL_VERSION | cut --delimiter='-' --field 1` - elif [[ ${KERNEL_VERSION:0:2} != "3." ]]; then - # dash is illegal character in rpm version so replace - # them with underscore like it is done in the kernel - # https://github.com/torvalds/linux/blob/master/scripts/package/mkspec#L25 - # but only for latest series of the kernel, not 3.x - - KERNEL_VERSION=`echo $KERNEL_VERSION | tr - _` - fi - - echo NOTE: if kernel-devel-$KERNEL_VERSION or kernel-headers-$KERNEL_VERSION installation - echo failed, please, provide a repository with the package, or yum update / reboot - echo your machine to get the latest kernel. - - install_package kernel-devel-$KERNEL_VERSION - install_package kernel-headers-$KERNEL_VERSION - if is_service_enabled tls-proxy; then - install_package openssl-devel - fi - - elif is_ubuntu ; then - install_package linux-headers-$KERNEL_VERSION - if is_service_enabled tls-proxy; then - install_package libssl-dev - fi - fi } # load_ovs_kernel_modules() - load openvswitch kernel module @@ -120,16 +81,14 @@ function reload_ovs_kernel_modules { } # compile_ovs() - Compile OVS from source and load needed modules. -# Accepts two parameters: -# - first one is False by default and means that modules are not built and installed. -# - second optional parameter defines prefix for ovs compilation -# - third optional parameter defines localstatedir for ovs single machine runtime +# Accepts two optional parameters: +# - first optional parameter defines prefix for ovs compilation +# - second optional parameter defines localstatedir for ovs single machine runtime # Env variables OVS_REPO_NAME, OVS_REPO and OVS_BRANCH must be set function compile_ovs { local _pwd=$PWD - local build_modules=${1:-False} - local prefix=$2 - local localstatedir=$3 + local prefix=$1 + local localstatedir=$2 if [ -n "$prefix" ]; then prefix="--prefix=$prefix" @@ -139,32 +98,16 @@ function compile_ovs { localstatedir="--localstatedir=$localstatedir" fi - prepare_for_ovs_compilation $build_modules - - KERNEL_VERSION=$(uname -r) - major_version=$(echo "${KERNEL_VERSION}" | cut -d '.' -f1) - patch_level=$(echo "${KERNEL_VERSION}" | cut -d '.' -f2) - if [ "${major_version}" -gt 5 ] || [ "${major_version}" == 5 ] && [ "${patch_level}" -gt 5 ]; then - echo "NOTE: KERNEL VERSION is ${KERNEL_VERSION} and OVS doesn't support compiling " - echo "Kernel module for version higher than 5.5. Skipping module compilation..." - build_modules="False" - fi + prepare_for_ovs_compilation if [ ! -f configure ] ; then ./boot.sh fi if [ ! -f config.status ] || [ configure -nt config.status ] ; then - if [[ "$build_modules" == "True" ]]; then - ./configure $prefix $localstatedir --with-linux=/lib/modules/$(uname -r)/build - else - ./configure $prefix $localstatedir - fi + ./configure $prefix $localstatedir fi make -j$(($(nproc) + 1)) sudo make install - if [[ "$build_modules" == "True" ]]; then - sudo make INSTALL_MOD_DIR=kernel/net/openvswitch modules_install - fi reload_ovs_kernel_modules cd $_pwd From 70c041f2720b96f86bfddc72791a83555e65029b Mon Sep 17 00:00:00 2001 From: Rodolfo Alonso Hernandez Date: Tue, 28 Jul 2026 11:31:18 +0200 Subject: [PATCH 14/15] Update ``compile_ovs`` input parameters In [1], the ``compile_ovs`` method removed the first input parameter, named ``build_modules`` inside. This patch is updating the method call with the missing leftover. [1]https://review.opendev.org/c/openstack/devstack/+/998414 Related-Bug: #2161600 Signed-off-by: Rodolfo Alonso Hernandez Change-Id: Icef5b10edfecdcc6456133d6b7f88c57b47e14b0 --- lib/neutron_plugins/ovs_base | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/neutron_plugins/ovs_base b/lib/neutron_plugins/ovs_base index adabc56412..f2a35dd340 100644 --- a/lib/neutron_plugins/ovs_base +++ b/lib/neutron_plugins/ovs_base @@ -68,7 +68,7 @@ function _neutron_ovs_base_install_ubuntu_dkms { function _neutron_ovs_base_install_agent_packages { if [ "$Q_BUILD_OVS_FROM_GIT" == "True" ]; then remove_ovs_packages - compile_ovs False /usr/local /var + compile_ovs /usr/local /var load_conntrack_gre_module start_new_ovs else From 9b0a00865c2537338f72ed5b9b44a0d6bff16eb4 Mon Sep 17 00:00:00 2001 From: Rodolfo Alonso Hernandez Date: Thu, 2 Jul 2026 10:26:55 +0200 Subject: [PATCH 15/15] ovs: Fix OVS path mismatch when building from source with OVN ``compile_ovs`` was called with ``--localstatedir=/var``, causing all compiled OVS binaries to hardcode ``/var/run/openvswitch`` as the default runtime directory. However, the ``ovn_agent`` plugin derives ``OVS_RUNDIR`` from ``OVS_PREFIX`` as ``/usr/local/var/run/openvswitch``, creating a path mismatch that makes ``ovs-vsctl`` unable to reach the running ``ovsdb-server``. Additionally, ``start_new_ovs`` was unconditionally starting OVS during the install phase. When OVN is the backend, ``ovn_agent:_start_ovs`` later starts its own OVS instance with a separate database, but the orphaned ``ovs-vswitchd`` from ``start_new_ovs`` still holds the kernel datapath, preventing bridge creation. Fix both issues: - Remove the ``--localstatedir=/var`` override so the compiled default matches ``OVS_RUNDIR`` (autotools defaults localstatedir to ``${prefix}/var``). - Skip ``start_new_ovs`` when OVN services are enabled, since ``_start_ovs`` handles the full OVS lifecycle. - Fix the hardcoded DB path in ``start_new_ovs`` to match the compiled ``--prefix=/usr/local`` sysconfdir. Closes-Bug: #2158954 Assisted-By: Claude Opus 4.6 Signed-off-by: Rodolfo Alonso Hernandez Change-Id: I8f3a2c5e7d1b4a9f6e0c3d8b2a5f7e1d4c6b9a0e --- lib/neutron_plugins/ovs_base | 10 ++++++++-- lib/neutron_plugins/ovs_source | 3 ++- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/lib/neutron_plugins/ovs_base b/lib/neutron_plugins/ovs_base index f2a35dd340..fb3a154a00 100644 --- a/lib/neutron_plugins/ovs_base +++ b/lib/neutron_plugins/ovs_base @@ -68,9 +68,15 @@ function _neutron_ovs_base_install_ubuntu_dkms { function _neutron_ovs_base_install_agent_packages { if [ "$Q_BUILD_OVS_FROM_GIT" == "True" ]; then remove_ovs_packages - compile_ovs /usr/local /var + compile_ovs /usr/local load_conntrack_gre_module - start_new_ovs + # When OVN is the backend, ovn_agent:_start_ovs handles OVS + # lifecycle with its own DB and rundir. Starting OVS here would + # leave an orphaned ovs-vswitchd holding the kernel datapath, + # preventing the OVN-managed instance from creating bridges. + if ! is_service_enabled ovn-controller ovn-northd; then + start_new_ovs + fi else # Install deps install_package $(get_packages "openvswitch") diff --git a/lib/neutron_plugins/ovs_source b/lib/neutron_plugins/ovs_source index feb8f0acd0..e141b22368 100644 --- a/lib/neutron_plugins/ovs_source +++ b/lib/neutron_plugins/ovs_source @@ -128,7 +128,8 @@ function action_openvswitch { # start_new_ovs() - removes old ovs database, creates a new one and starts ovs function start_new_ovs { - sudo rm -f /etc/openvswitch/conf.db /etc/openvswitch/.conf.db~lock~ + # DB path must match the compiled --prefix=/usr/local sysconfdir + sudo rm -f /usr/local/etc/openvswitch/conf.db /usr/local/etc/openvswitch/.conf.db~lock~ sudo /usr/local/share/openvswitch/scripts/ovs-ctl start }