From 3f15fddf9712507831b6ef179147a459b505f6a5 Mon Sep 17 00:00:00 2001 From: Will Szumski Date: Thu, 30 Apr 2026 12:26:35 +0100 Subject: [PATCH 01/17] Adds os_family variable End goal is to reduce the reliance on facts for when we have the such details encoded in config. This is a step in that direction. Change-Id: I5a2d5f973a85efc4f561ececf2c83b2981a419b8 Signed-off-by: Will Szumski --- ansible/inventory/group_vars/all/globals | 11 +++++++++++ .../configuration/reference/os-distribution.rst | 11 +++++++++++ etc/kayobe/globals.yml | 8 ++++++++ 3 files changed, 30 insertions(+) diff --git a/ansible/inventory/group_vars/all/globals b/ansible/inventory/group_vars/all/globals index 54c562c87..dcea8d952 100644 --- a/ansible/inventory/group_vars/all/globals +++ b/ansible/inventory/group_vars/all/globals @@ -55,6 +55,17 @@ kayobe_ansible_user: "stack" # is "rocky". os_distribution: "rocky" +# Mapping from OS distribution name to OS family. Supported keys are +# "centos", "rocky", and "ubuntu". +os_family_map: + centos: RedHat + rocky: RedHat + ubuntu: Debian + +# OS family. Valid options are "RedHat" and "Debian". Default depends on +# os_distribution. +os_family: "{{ os_family_map[os_distribution | lower] }}" + # OS release. Valid options are "10-stream" when os_distribution is "centos", # "10" when os_distribution is "rocky", or "noble" when os_distribution is # "ubuntu". diff --git a/doc/source/configuration/reference/os-distribution.rst b/doc/source/configuration/reference/os-distribution.rst index 5f29d95ec..716f68777 100644 --- a/doc/source/configuration/reference/os-distribution.rst +++ b/doc/source/configuration/reference/os-distribution.rst @@ -20,6 +20,17 @@ is set to ``rocky`` it may be set to ``10``, and this is its default value. When ``os_distribution`` is set to ``ubuntu`` it may be set to ``noble``, and this is its default value. +The ``os_family_map`` variable in ``etc/kayobe/globals.yml`` maps +``os_distribution`` values to OS families. The default mapping is: + +* ``centos`` -> ``RedHat`` +* ``rocky`` -> ``RedHat`` +* ``ubuntu`` -> ``Debian`` + +The ``os_family`` variable in ``etc/kayobe/globals.yml`` defaults to +``{{ os_family_map[os_distribution | lower] }}``, and may be used by +configuration defaults that only need to distinguish between OS families. + These variables are used to set various defaults, including: * Bootstrap users diff --git a/etc/kayobe/globals.yml b/etc/kayobe/globals.yml index bcf9aca4e..2e15f3a42 100644 --- a/etc/kayobe/globals.yml +++ b/etc/kayobe/globals.yml @@ -48,6 +48,14 @@ # is "rocky". #os_distribution: +# Mapping from OS distribution name to OS family. Supported keys are +# "centos", "rocky", and "ubuntu". +#os_family_map: + +# OS family. Valid options are "RedHat" and "Debian". Default depends on +# os_distribution. +#os_family: + # OS release. Valid options are "10-stream" when os_distribution is "centos", # "10" when os_distribution is "rocky", or "noble" when os_distribution is # "ubuntu". From 4c25c48da33850037b52ca656018f6b6997d5f85 Mon Sep 17 00:00:00 2001 From: Will Szumski Date: Wed, 29 Apr 2026 18:02:39 +0100 Subject: [PATCH 02/17] Stop gathering facts in trust-store playbook The issue was that we were caching these with ansible_user and ansible_python_interpreter overriden. This caused failures later on. We still want to run this before the kayobe target venv has been added so that we can use the CA for installing software packages. Change-Id: Id6373aa5eef515f5d6bd3176f71fe8b35333a009 Signed-off-by: Will Szumski --- ansible/roles/trust-store/defaults/main.yml | 5 +++-- ansible/trust-store.yml | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/ansible/roles/trust-store/defaults/main.yml b/ansible/roles/trust-store/defaults/main.yml index 37bd1755a..1d6c20a89 100644 --- a/ansible/roles/trust-store/defaults/main.yml +++ b/ansible/roles/trust-store/defaults/main.yml @@ -1,8 +1,9 @@ --- trust_store_ca_certificates: [] +trust_store_os_family: "{{ os_family | default(ansible_facts.os_family) | lower }}" trust_store_ca_path_debian: /usr/local/share/ca-certificates trust_store_ca_path_redhat: /etc/pki/ca-trust/source/anchors -trust_store_ca_path: "{{ lookup('vars', 'trust_store_ca_path_' ~ ansible_facts.os_family | lower) }}" +trust_store_ca_path: "{{ lookup('vars', 'trust_store_ca_path_' ~ trust_store_os_family) }}" trust_store_update_cmd_debian: update-ca-certificates trust_store_update_cmd_redhat: update-ca-trust -trust_store_update_cmd: "{{ lookup('vars', 'trust_store_update_cmd_' ~ ansible_facts.os_family | lower) }}" +trust_store_update_cmd: "{{ lookup('vars', 'trust_store_update_cmd_' ~ trust_store_os_family) }}" diff --git a/ansible/trust-store.yml b/ansible/trust-store.yml index 69596a809..af74ce74e 100644 --- a/ansible/trust-store.yml +++ b/ansible/trust-store.yml @@ -1,7 +1,7 @@ --- - name: Add custom CAs to system trust store hosts: seed-hypervisor:seed:overcloud:infra-vms:ansible-control - gather_facts: true + gather_facts: false max_fail_percentage: >- {{ trust_store_max_fail_percentage | default(host_configure_max_fail_percentage) | From e288140260c9c0dce438d3d1f7065d6165a20edf Mon Sep 17 00:00:00 2001 From: Will Szumski Date: Mon, 27 Apr 2026 13:30:43 +0100 Subject: [PATCH 03/17] Avoid deprecated ansible_managed variable Replace ansible_managed usage in tracked Kayobe templates with kayobe_managed to avoid the DEFAULT_MANAGED_STR deprecation scheduled for removal in ansible-core 2.23. Use "Ansible managed" as the fallback value so rendered output matches the historical default text. https://docs.ansible.com/projects/ansible-core/devel/reference_appendices/config.html#default-managed-str Change-Id: I1a7a4a57115bdce8c7406d1a3b5f90d764944c7b Signed-off-by: Will Szumski --- ansible/inventory/group_vars/all/globals | 4 ++++ ansible/roles/apt/templates/auth.conf.j2 | 2 +- ansible/roles/apt/templates/kayobe.sources.j2 | 2 +- .../roles/dell-switch-bmp/templates/dell-switch-bmp.conf.j2 | 2 +- ansible/roles/kolla-build/templates/template-override.j2.j2 | 2 +- ansible/roles/public-openrc/templates/public-openrc.sh.j2 | 2 +- etc/kayobe/globals.yml | 4 ++++ 7 files changed, 13 insertions(+), 5 deletions(-) diff --git a/ansible/inventory/group_vars/all/globals b/ansible/inventory/group_vars/all/globals index 54c562c87..d1184febe 100644 --- a/ansible/inventory/group_vars/all/globals +++ b/ansible/inventory/group_vars/all/globals @@ -66,6 +66,10 @@ os_release: >- ############################################################################### # Ansible configuration. +# String used as the header comment in files managed by Kayobe. Default is +# "Ansible managed". +kayobe_managed: "Ansible managed" + # Filter to apply to the setup module when gathering facts. Default is to not # specify a filter. kayobe_ansible_setup_filter: "{{ omit }}" diff --git a/ansible/roles/apt/templates/auth.conf.j2 b/ansible/roles/apt/templates/auth.conf.j2 index a5abd10ae..128eb8070 100644 --- a/ansible/roles/apt/templates/auth.conf.j2 +++ b/ansible/roles/apt/templates/auth.conf.j2 @@ -1,4 +1,4 @@ -# {{ ansible_managed }} +# {{ kayobe_managed }} machine {{ auth.machine }} login {{ auth.login }} diff --git a/ansible/roles/apt/templates/kayobe.sources.j2 b/ansible/roles/apt/templates/kayobe.sources.j2 index bc99a19fe..83d83758f 100644 --- a/ansible/roles/apt/templates/kayobe.sources.j2 +++ b/ansible/roles/apt/templates/kayobe.sources.j2 @@ -1,4 +1,4 @@ -# {{ ansible_managed }} +# {{ kayobe_managed }} {% for repo in apt_repositories %} {% if reponame == repo.name | default('kayobe') %} diff --git a/ansible/roles/dell-switch-bmp/templates/dell-switch-bmp.conf.j2 b/ansible/roles/dell-switch-bmp/templates/dell-switch-bmp.conf.j2 index 068fe3bc2..4e36d22da 100644 --- a/ansible/roles/dell-switch-bmp/templates/dell-switch-bmp.conf.j2 +++ b/ansible/roles/dell-switch-bmp/templates/dell-switch-bmp.conf.j2 @@ -1,4 +1,4 @@ -# {{ ansible_managed }} +# {{ kayobe_managed }} # This file provides dnsmasq configuration for Dell Switches using Bare Metal # Provisioning (BMP). diff --git a/ansible/roles/kolla-build/templates/template-override.j2.j2 b/ansible/roles/kolla-build/templates/template-override.j2.j2 index ac8957267..0b9991c7c 100644 --- a/ansible/roles/kolla-build/templates/template-override.j2.j2 +++ b/ansible/roles/kolla-build/templates/template-override.j2.j2 @@ -1,4 +1,4 @@ -# {{ ansible_managed }} +# {{ kayobe_managed }} {% raw %} {% extends parent_template %} diff --git a/ansible/roles/public-openrc/templates/public-openrc.sh.j2 b/ansible/roles/public-openrc/templates/public-openrc.sh.j2 index 49225fc60..e0c5e400b 100644 --- a/ansible/roles/public-openrc/templates/public-openrc.sh.j2 +++ b/ansible/roles/public-openrc/templates/public-openrc.sh.j2 @@ -1,4 +1,4 @@ -# {{ ansible_managed }} +# {{ kayobe_managed }} {% for line in (admin_openrc.content | b64decode).splitlines() %} {% if "export OS_AUTH_URL" in line %} diff --git a/etc/kayobe/globals.yml b/etc/kayobe/globals.yml index bcf9aca4e..3ff58c690 100644 --- a/etc/kayobe/globals.yml +++ b/etc/kayobe/globals.yml @@ -56,6 +56,10 @@ ############################################################################### # Ansible configuration. +# String used as the header comment in files managed by Kayobe. Default is +# "Ansible managed". +#kayobe_managed: + # Filter to apply to the setup module when gathering facts. Default is to not # specify a filter. #kayobe_ansible_setup_filter: From dfdf27752c629badc5d83ea70cd4b6c25fae086e Mon Sep 17 00:00:00 2001 From: Will Szumski Date: Wed, 29 Apr 2026 09:44:42 +0100 Subject: [PATCH 04/17] Stop caching kolla_ansible_host_vars facts The kolla_ansible_host_vars action plugin previously returned facts via ansible_facts with _ansible_facts_cacheable set to False. This prevented the plugin from directly writing to the fact cache, but facts already in the in-memory ansible_facts dict can still be persisted by later cache writes (e.g. from gather_facts with gathering = smart), resulting in a partial and potentially stale fact set being loaded on subsequent runs. Fix this by returning facts under a custom kolla_ansible_host_vars result key instead. The playbook then applies them as host variables using a single set_fact task, which writes to the host vars scope and is never persisted to the fact cache. Closes-Bug: #2144548 Change-Id: I5b8827f9e95992d4a63d5fc96fbd131531dfd439 Signed-off-by: Will Szumski --- ansible/kayobe-target-venv.yml | 4 +- ansible/kolla-ansible.yml | 10 ++++ .../roles/docker-registry/defaults/main.yml | 4 ++ .../plugins/action/kolla_ansible_host_vars.py | 3 +- .../action/test_kolla_ansible_host_vars.py | 48 +++++++------------ 5 files changed, 32 insertions(+), 37 deletions(-) diff --git a/ansible/kayobe-target-venv.yml b/ansible/kayobe-target-venv.yml index 4d4ae092f..53005c86e 100644 --- a/ansible/kayobe-target-venv.yml +++ b/ansible/kayobe-target-venv.yml @@ -26,9 +26,7 @@ filter: "{{ kayobe_ansible_setup_filter }}" gather_subset: "{{ kayobe_ansible_setup_gather_subset }}" when: - #TODO(mattcrees): Enable this check once this bug is fixed: - # https://bugs.launchpad.net/kayobe/+bug/2144548 - # - ansible_facts is undefined or ansible_facts is falsy + - ansible_facts is undefined or ansible_facts is falsy - kayobe_virtualenv is defined register: gather_facts_result # Before any facts are gathered, ansible doesn't know about diff --git a/ansible/kolla-ansible.yml b/ansible/kolla-ansible.yml index 01abf815c..7d0ba2cc5 100644 --- a/ansible/kolla-ansible.yml +++ b/ansible/kolla-ansible.yml @@ -143,6 +143,11 @@ description: "Bifrost provisioning network" network: "{{ provision_oc_net_name }}" required: "{{ kolla_enable_bifrost | bool }}" + register: kolla_host_vars_result + + - name: Set Kolla Ansible host variable facts + set_fact: + args: "{{ kolla_host_vars_result.kolla_ansible_host_vars }}" - import_role: name: kolla-ansible-host-vars @@ -229,6 +234,11 @@ network: "{{ public_net_name }}" required: "{{ inventory_hostname in groups[controller_loadbalancer_group] }}" external_networks: "{{ ironic_networks + provider_networks }}" + register: kolla_host_vars_result + + - name: Set Kolla Ansible host variable facts + set_fact: + args: "{{ kolla_host_vars_result.kolla_ansible_host_vars }}" - import_role: name: kolla-ansible-host-vars diff --git a/ansible/roles/docker-registry/defaults/main.yml b/ansible/roles/docker-registry/defaults/main.yml index 51e5ce4a2..5107b3a55 100644 --- a/ansible/roles/docker-registry/defaults/main.yml +++ b/ansible/roles/docker-registry/defaults/main.yml @@ -95,3 +95,7 @@ docker_registry_volumes: docker_registry_restart_policy: "unless-stopped" #docker_registry_restart_retries: + +# Owner and group for docker registry configuration files. +docker_registry_ansible_user_uid: "{{ ansible_user }}" +docker_registry_ansible_user_gid: "{{ ansible_user }}" diff --git a/kayobe/plugins/action/kolla_ansible_host_vars.py b/kayobe/plugins/action/kolla_ansible_host_vars.py index 085e60004..229b71306 100644 --- a/kayobe/plugins/action/kolla_ansible_host_vars.py +++ b/kayobe/plugins/action/kolla_ansible_host_vars.py @@ -96,8 +96,7 @@ def _run(self, interfaces, external_networks): result['failed'] = True result['msg'] = "; ".join(errors) else: - result['ansible_facts'] = facts - result['_ansible_facts_cacheable'] = False + result['kolla_ansible_host_vars'] = facts return result def _get_interface_fact(self, net_name, required, description): diff --git a/kayobe/tests/unit/plugins/action/test_kolla_ansible_host_vars.py b/kayobe/tests/unit/plugins/action/test_kolla_ansible_host_vars.py index 480a5cf2a..dcd2f3cbd 100644 --- a/kayobe/tests/unit/plugins/action/test_kolla_ansible_host_vars.py +++ b/kayobe/tests/unit/plugins/action/test_kolla_ansible_host_vars.py @@ -96,8 +96,7 @@ def test__run_empty_args(self): result = module._run([], []) expected = { "changed": False, - "ansible_facts": {}, - "_ansible_facts_cacheable": False, + "kolla_ansible_host_vars": {}, } self.assertEqual(expected, result) @@ -112,10 +111,9 @@ def test__run_one_interface(self): result = module._run(interfaces, []) expected = { "changed": False, - "ansible_facts": { + "kolla_ansible_host_vars": { "kolla_foo_interface": "eth0", }, - "_ansible_facts_cacheable": False, } self.assertEqual(expected, result) @@ -135,11 +133,10 @@ def test__run_two_interfaces(self): result = module._run(interfaces, []) expected = { "changed": False, - "ansible_facts": { + "kolla_ansible_host_vars": { "kolla_foo_interface": "eth0", "kolla_bar_interface": "eth1", }, - "_ansible_facts_cacheable": False, } self.assertEqual(expected, result) @@ -171,8 +168,7 @@ def test__run_interface_not_mapped_not_required(self): result = module._run(interfaces, []) expected = { "changed": False, - "ansible_facts": {}, - "_ansible_facts_cacheable": False, + "kolla_ansible_host_vars": {}, } self.assertEqual(expected, result) @@ -208,8 +204,7 @@ def test__run_interface_no_interface_not_required(self): result = module._run(interfaces, []) expected = { "changed": False, - "ansible_facts": {}, - "_ansible_facts_cacheable": False, + "kolla_ansible_host_vars": {}, } self.assertEqual(expected, result) @@ -247,11 +242,10 @@ def test_run_external_networks_one(self): result = module._run([], external_networks) expected = { "changed": False, - "ansible_facts": { + "kolla_ansible_host_vars": { "kolla_neutron_bridge_names": "eth0-ovs", "kolla_neutron_external_interfaces": "eth0", }, - "_ansible_facts_cacheable": False, } self.assertEqual(expected, result) @@ -266,12 +260,11 @@ def test_run_external_networks_one_with_physnet(self): result = module._run([], external_networks) expected = { "changed": False, - "ansible_facts": { + "kolla_ansible_host_vars": { "kolla_neutron_bridge_names": "eth0-ovs", "kolla_neutron_external_interfaces": "eth0", "kolla_neutron_physical_networks": "custom1", }, - "_ansible_facts_cacheable": False, } self.assertEqual(expected, result) @@ -287,11 +280,10 @@ def test_run_external_networks_two(self): result = module._run([], external_networks) expected = { "changed": False, - "ansible_facts": { + "kolla_ansible_host_vars": { "kolla_neutron_bridge_names": "eth0-ovs,eth1-ovs", "kolla_neutron_external_interfaces": "eth0,eth1", }, - "_ansible_facts_cacheable": False, } self.assertEqual(expected, result) @@ -310,12 +302,11 @@ def test_run_external_networks_two_with_physnet(self): result = module._run([], external_networks) expected = { "changed": False, - "ansible_facts": { + "kolla_ansible_host_vars": { "kolla_neutron_bridge_names": "eth0-ovs,eth1-ovs", "kolla_neutron_external_interfaces": "eth0,eth1", "kolla_neutron_physical_networks": "custom1,custom2", }, - "_ansible_facts_cacheable": False, } self.assertEqual(expected, result) @@ -353,11 +344,10 @@ def test_run_external_networks_two_same_interface(self): result = module._run([], external_networks) expected = { "changed": False, - "ansible_facts": { + "kolla_ansible_host_vars": { "kolla_neutron_bridge_names": "eth0-ovs", "kolla_neutron_external_interfaces": "eth0", }, - "_ansible_facts_cacheable": False, } self.assertEqual(expected, result) @@ -376,12 +366,11 @@ def test_run_external_networks_two_same_interface_with_physnet(self): result = module._run([], external_networks) expected = { "changed": False, - "ansible_facts": { + "kolla_ansible_host_vars": { "kolla_neutron_bridge_names": "eth0-ovs", "kolla_neutron_external_interfaces": "eth0", "kolla_neutron_physical_networks": "custom1", }, - "_ansible_facts_cacheable": False, } self.assertEqual(expected, result) @@ -424,11 +413,10 @@ def test_run_external_networks_two_vlans(self): result = module._run([], external_networks) expected = { "changed": False, - "ansible_facts": { + "kolla_ansible_host_vars": { "kolla_neutron_bridge_names": "eth0-ovs", "kolla_neutron_external_interfaces": "eth0", }, - "_ansible_facts_cacheable": False, } self.assertEqual(expected, result) @@ -443,11 +431,10 @@ def test_run_external_networks_bridge(self): result = module._run([], external_networks) expected = { "changed": False, - "ansible_facts": { + "kolla_ansible_host_vars": { "kolla_neutron_bridge_names": "breth0-ovs", "kolla_neutron_external_interfaces": "p-breth0-ovs", }, - "_ansible_facts_cacheable": False, } self.assertEqual(expected, result) @@ -463,11 +450,10 @@ def test_run_external_networks_bridge_vlan(self): result = module._run([], external_networks) expected = { "changed": False, - "ansible_facts": { + "kolla_ansible_host_vars": { "kolla_neutron_bridge_names": "breth0-ovs", "kolla_neutron_external_interfaces": "p-breth0-ovs", }, - "_ansible_facts_cacheable": False, } self.assertEqual(expected, result) @@ -495,8 +481,7 @@ def test_run_external_networks_not_mapped_not_required(self): result = module._run([], external_networks) expected = { "changed": False, - "ansible_facts": {}, - "_ansible_facts_cacheable": False, + "kolla_ansible_host_vars": {}, } self.assertEqual(expected, result) @@ -528,8 +513,7 @@ def test_run_external_networks_no_interface_not_required(self): result = module._run([], external_networks) expected = { "changed": False, - "ansible_facts": {}, - "_ansible_facts_cacheable": False, + "kolla_ansible_host_vars": {}, } self.assertEqual(expected, result) From 758516fd05d46fec243b0047c3caefc8a92d03a2 Mon Sep 17 00:00:00 2001 From: Will Szumski Date: Wed, 13 May 2026 17:41:34 +0100 Subject: [PATCH 05/17] [release] Use OpenStack 2026.1 release Switch all dependencies to use the OpenStack 2026.1 release. This commit should be reverted on the master branch once the Kayobe stable/2026.1 branch has been cut and RC1 released. Change-Id: I8fa9a48dd887497312812a064523a1ccc5b8bdaf Signed-off-by: Will Szumski --- ansible/inventory/group_vars/all/openstack | 6 +++--- etc/kayobe/openstack.yml | 4 ++-- requirements.yml | 2 +- tox.ini | 8 ++++---- zuul.d/jobs.yaml | 8 ++++++++ 5 files changed, 18 insertions(+), 10 deletions(-) diff --git a/ansible/inventory/group_vars/all/openstack b/ansible/inventory/group_vars/all/openstack index 430293d3f..a7a6e4312 100644 --- a/ansible/inventory/group_vars/all/openstack +++ b/ansible/inventory/group_vars/all/openstack @@ -2,10 +2,10 @@ ############################################################################### # OpenStack release configuration. -# Name of the current OpenStack release. Default is "master". -openstack_release: "master" +# Name of the current OpenStack release. Default is "2026.1". +openstack_release: "2026.1" -# Name of the current OpenStack branch. Default is "master". +# Name of the current OpenStack branch. Default is "stable/2026.1". openstack_branch: >- {% if openstack_release != 'master' %}stable/{% endif %}{{ openstack_release | lower }} diff --git a/etc/kayobe/openstack.yml b/etc/kayobe/openstack.yml index 1acfd0756..688b6f4c0 100644 --- a/etc/kayobe/openstack.yml +++ b/etc/kayobe/openstack.yml @@ -2,10 +2,10 @@ ############################################################################### # OpenStack release configuration. -# Name of the current OpenStack release. Default is "master". +# Name of the current OpenStack release. Default is "2026.1". #openstack_release: -# Name of the current OpenStack branch. Default is "master". +# Name of the current OpenStack branch. Default is "stable/2026.1". #openstack_branch: ############################################################################### diff --git a/requirements.yml b/requirements.yml index c7402326a..c8e961776 100644 --- a/requirements.yml +++ b/requirements.yml @@ -2,7 +2,7 @@ collections: - name: https://opendev.org/openstack/ansible-collection-kolla type: git - version: master + version: stable/2026.1 - name: community.docker version: 5.1.0 - name: community.network diff --git a/tox.ini b/tox.ini index 86f549130..6f173d62d 100644 --- a/tox.ini +++ b/tox.ini @@ -19,7 +19,7 @@ setenv = OS_TEST_TIMEOUT=60 ANSIBLE_VERBOSITY=3 deps = - -c{env:TOX_CONSTRAINTS_FILE:https://releases.openstack.org/constraints/upper/master} + -c{env:TOX_CONSTRAINTS_FILE:https://releases.openstack.org/constraints/upper/2026.1} -r{toxinidir}/requirements.txt -r{toxinidir}/test-requirements.txt commands = stestr run {posargs} @@ -42,7 +42,7 @@ commands = [testenv:venv] deps = - -c{env:TOX_CONSTRAINTS_FILE:https://releases.openstack.org/constraints/upper/master} + -c{env:TOX_CONSTRAINTS_FILE:https://releases.openstack.org/constraints/upper/2026.1} -r{toxinidir}/test-requirements.txt -r{toxinidir}/doc/requirements.txt commands = {posargs} @@ -60,7 +60,7 @@ commands = [testenv:molecule] deps = - -c{env:TOX_CONSTRAINTS_FILE:https://releases.openstack.org/constraints/upper/master} + -c{env:TOX_CONSTRAINTS_FILE:https://releases.openstack.org/constraints/upper/2026.1} -r{toxinidir}/requirements.txt -r{toxinidir}/molecule-requirements.txt commands = @@ -130,7 +130,7 @@ commands = [testenv:docs] deps = - -c{env:TOX_CONSTRAINTS_FILE:https://releases.openstack.org/constraints/upper/master} + -c{env:TOX_CONSTRAINTS_FILE:https://releases.openstack.org/constraints/upper/2026.1} -r{toxinidir}/doc/requirements.txt commands = rm -rf doc/build/html diff --git a/zuul.d/jobs.yaml b/zuul.d/jobs.yaml index ecd50c249..087a2d663 100644 --- a/zuul.d/jobs.yaml +++ b/zuul.d/jobs.yaml @@ -71,11 +71,19 @@ required-projects: # Include kayobe to ensure other projects can use this job. - name: openstack/ansible-collection-kolla + # TODO(wszumski): Remove when kayobe stable/2026.1 exists. + override-checkout: stable/2026.1 - name: openstack/kayobe - name: openstack/kayobe-config-dev - name: openstack/kolla + # TODO(wszumski): Remove when kayobe stable/2026.1 exists. + override-checkout: stable/2026.1 - name: openstack/kolla-ansible + # TODO(wszumski): Remove when kayobe stable/2026.1 exists. + override-checkout: stable/2026.1 - name: openstack/requirements + # TODO(wszumski): Remove when kayobe stable/2026.1 exists. + override-checkout: stable/2026.1 - name: openstack/tenks irrelevant-files: - ^\..+ From 92ccce0da0c750ed8f56a13d576413cfb179f2ab Mon Sep 17 00:00:00 2001 From: Grzegorz Koper Date: Fri, 8 May 2026 12:20:14 +0200 Subject: [PATCH 06/17] tests: trim low-signal nmstate unit test permutations Drop a small set of nmstate unit tests that duplicate behavior already covered by more targeted cases. Signed-off-by: Grzegorz Koper Change-Id: I0dd549a0066eb4076941af3ac417181a16dc096f --- .../tests/unit/plugins/filter/test_nmstate.py | 83 +------------------ 1 file changed, 1 insertion(+), 82 deletions(-) diff --git a/kayobe/tests/unit/plugins/filter/test_nmstate.py b/kayobe/tests/unit/plugins/filter/test_nmstate.py index 91c5966c8..da1fef140 100644 --- a/kayobe/tests/unit/plugins/filter/test_nmstate.py +++ b/kayobe/tests/unit/plugins/filter/test_nmstate.py @@ -327,29 +327,6 @@ def test_ethtool_feature_aliases(self): } self.assertEqual(eth_iface["ethtool"]["feature"], expected_features) - def test_ethtool_combined_config(self): - """Test combined ring and feature configuration.""" - variables = { - "inventory_hostname": "test-host", - "test_interface": "eth0", - "test_ethtool_config": { - "ring": {"rx": 1024, "tx": 512}, - "feature": {"rx": True, "gso": False} - } - } - context = self._make_context(variables) - result = nmstate.nmstate_config(context, ["test"]) - - eth_iface = next(i for i in result["interfaces"] - - - if i["name"] == "eth0") - expected_ethtool = { - "ring": {"rx": 1024, "tx": 512}, - "feature": {"rx-checksum": True, "tx-generic-segmentation": False} - } - self.assertEqual(eth_iface["ethtool"], expected_ethtool) - def test_ethtool_invalid_feature(self): """Test error handling for unsupported features.""" variables = { @@ -472,28 +449,6 @@ def test_vlan_interface_invalid_name(self): if i["name"] == "eth0") self.assertEqual(eth_iface["type"], "ethernet") - def test_vlan_interface_parent_derivation(self): - """Test VLAN parent derivation from interface name.""" - variables = { - "inventory_hostname": "test-host", - "ansible_facts": {"os_family": "RedHat"}, - "vlan_interface": "bond0.42", - "vlan_vlan": 42, - } - context = self._make_context(variables) - result = nmstate.nmstate_config(context, ["vlan"]) - - vlan_iface = next( - i for i in result["interfaces"] - if i["name"] == "bond0.42") - self.assertEqual(vlan_iface["vlan"]["base-iface"], "bond0") - self.assertEqual(vlan_iface["vlan"]["id"], 42) - - bond_iface = next( - i for i in result["interfaces"] - if i["name"] == "bond0") - self.assertEqual(bond_iface["state"], "up") - def test_vlan_interface_qos_map_structured(self): context = self._make_context( { @@ -639,25 +594,6 @@ def test_defroute_true_static_ip(self): self.assertEqual(default_routes[0]["next-hop-address"], "10.0.0.254") - def test_defroute_unset_static_ip(self): - """Test defroute unset (None) adds default route for static IP.""" - variables = { - "inventory_hostname": "test-host", - "test_interface": "eth0", - "test_ips": {"test-host": "10.0.0.1"}, - "test_cidr": "10.0.0.1/24", - "test_gateway": "10.0.0.254", - } - context = self._make_context(variables) - result = nmstate.nmstate_config(context, ["test"]) - - default_routes = [ - r for r in result["routes"]["config"] - if r["destination"] == "0.0.0.0/0"] - self.assertEqual(len(default_routes), 1) - self.assertEqual(default_routes[0]["next-hop-address"], - "10.0.0.254") - def test_defroute_false_dhcp(self): """Test defroute=false disables auto-routes for DHCP.""" variables = { @@ -744,24 +680,6 @@ def test_ovs_patch_links(self): self.assertIn({"name": "eth1"}, bridge_ports) self.assertIn({"name": "p-br0-phy"}, bridge_ports) - def test_route_without_table(self): - """Test route without table-id omits the field.""" - variables = { - "inventory_hostname": "test-host", - "test_interface": "eth0", - "test_routes": [ - {"cidr": "10.0.0.0/24", "gateway": "192.168.1.1"} - ], - } - context = self._make_context(variables) - result = nmstate.nmstate_config(context, ["test"]) - - routes = result["routes"]["config"] - self.assertEqual(len(routes), 1) - self.assertEqual(routes[0]["destination"], "10.0.0.0/24") - self.assertEqual(routes[0]["next-hop-address"], "192.168.1.1") - self.assertNotIn("table-id", routes[0]) - def test_route_with_supported_attributes(self): """Test route maps supported nmstate attributes.""" variables = { @@ -785,6 +703,7 @@ def test_route_with_supported_attributes(self): self.assertEqual(routes[0]["metric"], 400) self.assertTrue(routes[0]["on-link"]) self.assertEqual(routes[0]["source"], "192.168.1.2") + self.assertNotIn("table-id", routes[0]) def test_route_with_supported_options(self): """Test documented route options map to nmstate attributes.""" From 43294efe8ce9677d56929ae4e79e2c66c25f97f2 Mon Sep 17 00:00:00 2001 From: Pierre Riteau Date: Tue, 19 May 2026 19:16:10 +0200 Subject: [PATCH 07/17] CI: Exclude docker-ce 29.5.1 on CentOS/Rocky Linux Related-Bug: #2153110 Change-Id: I0ef2c3dc5bfb87fc2f18f6fb92cd5f0f3e546577 Co-Authored-By: Michal Nasiadka Signed-off-by: Pierre Riteau --- roles/kayobe-ci-prep/tasks/main.yml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/roles/kayobe-ci-prep/tasks/main.yml b/roles/kayobe-ci-prep/tasks/main.yml index 942a1988a..0a83521f7 100644 --- a/roles/kayobe-ci-prep/tasks/main.yml +++ b/roles/kayobe-ci-prep/tasks/main.yml @@ -62,5 +62,19 @@ - openssl-devel when: not kayobe_control_host_become | bool + # NOTE(priteau): Remove me when newer docker-ce package is out + - name: Install python3-dnf-plugin-versionlock + become: true + ansible.builtin.dnf: + name: python3-dnf-plugin-versionlock + state: present + + - name: Pin docker-ce to 29.5.0 + become: true + community.general.dnf_versionlock: + name: "docker-ce-3:29.5.1-1.el{{ ansible_facts.distribution_major_version }}" + state: excluded + raw: true + when: ansible_facts.os_family == 'RedHat' become: true From 297c74f810fab999e3d2d55853b89622287bc73e Mon Sep 17 00:00:00 2001 From: Pierre Riteau Date: Tue, 19 May 2026 22:50:05 +0200 Subject: [PATCH 08/17] Bump Ansible collections and roles Bump community.docker to 5.2.0, MichaelRigart.interfaces to v1.17.0 and stackhpc.libvirt-vm to v1.16.4. Update jriguera.configdrive to the latest commit SHA. Change-Id: Ib42e07912d1fbffe4a82584f26126ff953585879 Signed-off-by: Pierre Riteau --- requirements.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/requirements.yml b/requirements.yml index 352609203..d96920de6 100644 --- a/requirements.yml +++ b/requirements.yml @@ -4,7 +4,7 @@ collections: type: git version: master - name: community.docker - version: 5.1.0 + version: 5.2.0 - name: community.network version: 5.1.0 - name: dellemc.os6 @@ -31,9 +31,9 @@ roles: version: 2.0.2 - src: jriguera.configdrive # There are no versioned releases of this role. - version: c6da1f29d6c1d8d5e0f9f0d2dd2d4dfb1973e62d + version: ebf31eee91056a8fcc71a304ff50b014909cf4ca - src: MichaelRigart.interfaces - version: v1.16.1 + version: v1.17.0 - src: mrlesmithjr.chrony version: v0.2.0 - src: mrlesmithjr.manage_lvm @@ -51,7 +51,7 @@ roles: - src: stackhpc.libvirt-host version: v1.15.1 - src: stackhpc.libvirt-vm - version: v1.16.3 + version: v1.16.4 - src: stackhpc.luks version: 0.4.4 - src: stackhpc.os-ironic-state From 31ba46b4ce0d00bbf3ad501c0ed385efedd98641 Mon Sep 17 00:00:00 2001 From: Will Szumski Date: Thu, 23 Apr 2026 12:24:42 +0100 Subject: [PATCH 09/17] Adds support for custom watcher configuration files Closes-Bug: #2148457 Change-Id: I3618a2b1050b69a031a5d09e30269fcfbddeff8d Signed-off-by: Will Szumski --- ansible/roles/kolla-openstack/defaults/main.yml | 10 ++++++++++ .../molecule/enable-everything/molecule.yml | 1 + .../molecule/enable-everything/prepare.yml | 6 ++++++ .../molecule/enable-everything/tests/test_default.py | 4 +++- doc/source/configuration/reference/kolla-ansible.rst | 2 ++ ...r-watcher-custom-config-files-01ebecc4feb232db.yaml | 4 ++++ 6 files changed, 26 insertions(+), 1 deletion(-) create mode 100644 releasenotes/notes/add-support-for-watcher-custom-config-files-01ebecc4feb232db.yaml diff --git a/ansible/roles/kolla-openstack/defaults/main.yml b/ansible/roles/kolla-openstack/defaults/main.yml index 0feb15251..b87b54566 100644 --- a/ansible/roles/kolla-openstack/defaults/main.yml +++ b/ansible/roles/kolla-openstack/defaults/main.yml @@ -148,6 +148,10 @@ kolla_openstack_custom_config_include_globs_default: glob: prometheus/** - enabled: '{{ kolla_enable_swift | bool }}' glob: swift/** + - enabled: '{{ kolla_enable_watcher | bool }}' + glob: watcher.conf + - enabled: '{{ kolla_enable_watcher | bool }}' + glob: watcher/** # Extra items to add to kolla_openstack_custom_config_include_globs_default # to produce kolla_openstack_custom_config_include_globs. @@ -795,3 +799,9 @@ kolla_enable_prometheus: false # Whether to enable swift. kolla_enable_swift: false + +############################################################################### +# Watcher configuration. + +# Whether to enable watcher +kolla_enable_watcher: false diff --git a/ansible/roles/kolla-openstack/molecule/enable-everything/molecule.yml b/ansible/roles/kolla-openstack/molecule/enable-everything/molecule.yml index 035a4cb09..6bd7da34d 100644 --- a/ansible/roles/kolla-openstack/molecule/enable-everything/molecule.yml +++ b/ansible/roles/kolla-openstack/molecule/enable-everything/molecule.yml @@ -137,6 +137,7 @@ provisioner: kolla_enable_prometheus: true kolla_enable_swift: true kolla_enable_telegraf: true + kolla_enable_watcher: true lint: name: ansible-lint scenario: diff --git a/ansible/roles/kolla-openstack/molecule/enable-everything/prepare.yml b/ansible/roles/kolla-openstack/molecule/enable-everything/prepare.yml index 4e945b3aa..913f3768e 100644 --- a/ansible/roles/kolla-openstack/molecule/enable-everything/prepare.yml +++ b/ansible/roles/kolla-openstack/molecule/enable-everything/prepare.yml @@ -40,6 +40,7 @@ - prometheus/prometheus.yml.d # Example of non-ini files that should be templated but not merged - fluentd/input/ + - watcher - name: Ensure extra INI configuration files exist copy: @@ -74,6 +75,7 @@ - nova.conf - octavia.conf - placement.conf + - watcher.conf - name: Ensure extra YAML configuration files exist copy: @@ -113,6 +115,10 @@ format1 /^(?\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d{3}) \[(?\w+)\] (?.*)/ + - dest: watcher/policy.yaml + content: | + --- + "my_custom_rule": "role:custom_role" loop_control: label: "{{ item.dest }}" diff --git a/ansible/roles/kolla-openstack/molecule/enable-everything/tests/test_default.py b/ansible/roles/kolla-openstack/molecule/enable-everything/tests/test_default.py index 72d74d0b0..50c524459 100644 --- a/ansible/roles/kolla-openstack/molecule/enable-everything/tests/test_default.py +++ b/ansible/roles/kolla-openstack/molecule/enable-everything/tests/test_default.py @@ -78,6 +78,7 @@ def test_service_ini_file(host, path): 'nova.conf', 'octavia.conf', 'placement.conf', + 'watcher.conf', 'backup.my.cnf']) def test_service_ini_file_extra_confs(host, path): # Tests config added via extra config files @@ -92,7 +93,8 @@ def test_service_ini_file_extra_confs(host, path): 'ironic/ironic-agent.kernel', 'nova/nova-libvirt/cacert.pem', 'nova/nova-libvirt/clientcert.pem', - 'nova/nova-libvirt/clientkey.pem']) + 'nova/nova-libvirt/clientkey.pem', + 'watcher/policy.yaml']) def test_service_non_ini_file(host, path): # TODO(mgoddard): Check config file contents. path = os.path.join('/etc/kolla/config', path) diff --git a/doc/source/configuration/reference/kolla-ansible.rst b/doc/source/configuration/reference/kolla-ansible.rst index aa748bc6c..ea2f6e85e 100644 --- a/doc/source/configuration/reference/kolla-ansible.rst +++ b/doc/source/configuration/reference/kolla-ansible.rst @@ -829,6 +829,8 @@ which files are supported. ``placement/*`` Extended Placement configuration. ``prometheus/*`` Prometheus configuration. ``swift/*`` Extended swift configuration. + ``watcher.conf`` Watcher configuration. + ``watcher/*`` Extended Watcher configuration. =============================== ======================================================= Configuring an OpenStack Component diff --git a/releasenotes/notes/add-support-for-watcher-custom-config-files-01ebecc4feb232db.yaml b/releasenotes/notes/add-support-for-watcher-custom-config-files-01ebecc4feb232db.yaml new file mode 100644 index 000000000..2f8fa291a --- /dev/null +++ b/releasenotes/notes/add-support-for-watcher-custom-config-files-01ebecc4feb232db.yaml @@ -0,0 +1,4 @@ +--- +features: + - Adds support for custom Watcher configuration via ``watcher.conf`` and + ``watcher/*`` files. From eb5ab490e88c907e032f22c3c5bf953c3d368327 Mon Sep 17 00:00:00 2001 From: Pierre Riteau Date: Wed, 20 May 2026 12:59:51 +0200 Subject: [PATCH 10/17] CI: Replace use of deprecated cp -n option The following warning was visible in CI logs: cp: warning: behavior of -n is non-portable and may change in future; use --update=none instead Change-Id: I915561e73108fa0c4c1e977a3b88271f69ff6002 Signed-off-by: Pierre Riteau --- roles/kayobe-diagnostics/files/get_logs.sh | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/roles/kayobe-diagnostics/files/get_logs.sh b/roles/kayobe-diagnostics/files/get_logs.sh index 267563523..29d943514 100644 --- a/roles/kayobe-diagnostics/files/get_logs.sh +++ b/roles/kayobe-diagnostics/files/get_logs.sh @@ -41,11 +41,11 @@ copy_bifrost_logs() { } copy_logs() { - cp -rnL /var/log/kolla/* ${LOG_DIR}/kolla/ + cp -rL --update=none /var/log/kolla/* ${LOG_DIR}/kolla/ if [[ -d ${CONFIG_DIR} ]]; then - cp -rnL ${CONFIG_DIR}/etc/kayobe/* ${LOG_DIR}/kayobe_configs - cp -rnL ${CONFIG_DIR}/etc/kolla/* ${LOG_DIR}/kolla_configs - cp -rnL /etc/kolla/* ${LOG_DIR}/kolla_node_configs + cp -rL --update=none ${CONFIG_DIR}/etc/kayobe/* ${LOG_DIR}/kayobe_configs + cp -rL --update=none ${CONFIG_DIR}/etc/kolla/* ${LOG_DIR}/kolla_configs + cp -rL --update=none /etc/kolla/* ${LOG_DIR}/kolla_node_configs # Don't save the IPA images. rm ${LOG_DIR}/kayobe_configs/kolla/config/ironic/ironic-agent.{kernel,initramfs} rm ${LOG_DIR}/kolla_configs/config/ironic/ironic-agent.{kernel,initramfs} @@ -54,8 +54,8 @@ copy_logs() { fi if [[ -n ${PREVIOUS_CONFIG_DIR} ]] && [[ -d ${PREVIOUS_CONFIG_DIR} ]]; then mkdir -p ${LOG_DIR}/previous_{kayobe,kolla}_configs - cp -rnL ${PREVIOUS_CONFIG_DIR}/etc/kayobe/* ${LOG_DIR}/previous_kayobe_configs - cp -rnL ${PREVIOUS_CONFIG_DIR}/etc/kolla/* ${LOG_DIR}/previous_kolla_configs + cp -rL --update=none ${PREVIOUS_CONFIG_DIR}/etc/kayobe/* ${LOG_DIR}/previous_kayobe_configs + cp -rL --update=none ${PREVIOUS_CONFIG_DIR}/etc/kolla/* ${LOG_DIR}/previous_kolla_configs # NOTE: we can't save node configs in /etc/kolla for the pervious # release since they'll have been overwritten at this point. # Don't save the IPA images. @@ -64,10 +64,10 @@ copy_logs() { fi if [[ -d /opt/kayobe/etc/kolla ]]; then - cp -rnL /opt/kayobe/etc/kolla/* ${LOG_DIR}/kolla_build_configs/ + cp -rL --update=none /opt/kayobe/etc/kolla/* ${LOG_DIR}/kolla_build_configs/ fi - cp -rvnL /var/log/* ${LOG_DIR}/system_logs/ + cp -rvL --update=none /var/log/* ${LOG_DIR}/system_logs/ if [[ -x "$(command -v journalctl)" ]]; then journalctl --no-pager > ${LOG_DIR}/system_logs/syslog.txt From 3145e7b3a4f589c8c33f872569cd17cbcf8ecbbd Mon Sep 17 00:00:00 2001 From: Will Szumski Date: Wed, 20 May 2026 19:01:33 +0100 Subject: [PATCH 11/17] Fix broken conditional release note formatting Change-Id: I677ff46661fe98f6cb3bc35f6e13a3b12bf39066 Signed-off-by: Will Szumski --- ...nsible-broken-conditionals-deprecation-7a0713c08d8a0a3d.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/releasenotes/notes/ansible-broken-conditionals-deprecation-7a0713c08d8a0a3d.yaml b/releasenotes/notes/ansible-broken-conditionals-deprecation-7a0713c08d8a0a3d.yaml index 36a2b6765..b9cc46fc1 100644 --- a/releasenotes/notes/ansible-broken-conditionals-deprecation-7a0713c08d8a0a3d.yaml +++ b/releasenotes/notes/ansible-broken-conditionals-deprecation-7a0713c08d8a0a3d.yaml @@ -1,7 +1,7 @@ --- deprecations: - | - Kayobe currently ships with ``ANSIBLE_ALLOW_BROKEN_CONDITIONALS` enabled by + Kayobe currently ships with ``ANSIBLE_ALLOW_BROKEN_CONDITIONALS`` enabled by default. This will be removed in the 2026.2 cycle. Please check the Ansible output of any custom playbooks for deprecation warnings related to this setting and update the playbooks accordingly. You can set From a2b7d9e3c480a6a7b3c964c433eb5f1c00e9a5b5 Mon Sep 17 00:00:00 2001 From: Pierre Riteau Date: Wed, 20 May 2026 23:05:27 +0200 Subject: [PATCH 12/17] [release] Sync with Kolla Ansible for 2026.1 Change-Id: Ib6bba94bf5938bdd84a71f42fde395659fe5a6f4 Signed-off-by: Pierre Riteau --- .../templates/overcloud-components.j2 | 1 - .../kolla-ansible/templates/overcloud-services.j2 | 14 ++++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/ansible/roles/kolla-ansible/templates/overcloud-components.j2 b/ansible/roles/kolla-ansible/templates/overcloud-components.j2 index 415c5c7d1..3eea3b95c 100644 --- a/ansible/roles/kolla-ansible/templates/overcloud-components.j2 +++ b/ansible/roles/kolla-ansible/templates/overcloud-components.j2 @@ -109,7 +109,6 @@ control [cyborg:children] control -compute [gnocchi:children] control diff --git a/ansible/roles/kolla-ansible/templates/overcloud-services.j2 b/ansible/roles/kolla-ansible/templates/overcloud-services.j2 index cd0a3cae5..4ac3d4b13 100644 --- a/ansible/roles/kolla-ansible/templates/overcloud-services.j2 +++ b/ansible/roles/kolla-ansible/templates/overcloud-services.j2 @@ -137,12 +137,26 @@ neutron cinder [cinder-backup:children] +cinder + +[cinder-backup-lvm:children] +storage + +[cinder-backup-multiple:children] +cinder storage [cinder-scheduler:children] cinder [cinder-volume:children] +cinder + +[cinder-volume-lvm:children] +storage + +[cinder-volume-multiple:children] +cinder storage # Cloudkitty From 908d87145590ccf3b4ec070cb9767a964a232955 Mon Sep 17 00:00:00 2001 From: Pierre Riteau Date: Thu, 21 May 2026 09:57:10 +0200 Subject: [PATCH 13/17] Revert "CI: Exclude docker-ce 29.5.1 on CentOS/Rocky Linux" Docker Engine 29.5.2 is out and fixes the regression introduced in 29.5.1 [1]. This reverts commit 43294efe8ce9677d56929ae4e79e2c66c25f97f2. [1] https://docs.docker.com/engine/release-notes/29/#2952 Closes-Bug: #2153110 Change-Id: Ib1ce90cd9174a190248e11512308828a2719ba49 Signed-off-by: Pierre Riteau --- roles/kayobe-ci-prep/tasks/main.yml | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/roles/kayobe-ci-prep/tasks/main.yml b/roles/kayobe-ci-prep/tasks/main.yml index 0a83521f7..942a1988a 100644 --- a/roles/kayobe-ci-prep/tasks/main.yml +++ b/roles/kayobe-ci-prep/tasks/main.yml @@ -62,19 +62,5 @@ - openssl-devel when: not kayobe_control_host_become | bool - # NOTE(priteau): Remove me when newer docker-ce package is out - - name: Install python3-dnf-plugin-versionlock - become: true - ansible.builtin.dnf: - name: python3-dnf-plugin-versionlock - state: present - - - name: Pin docker-ce to 29.5.0 - become: true - community.general.dnf_versionlock: - name: "docker-ce-3:29.5.1-1.el{{ ansible_facts.distribution_major_version }}" - state: excluded - raw: true - when: ansible_facts.os_family == 'RedHat' become: true From 95ef96e5f1b4be75a784b2a694798ae069a29478 Mon Sep 17 00:00:00 2001 From: Pierre Riteau Date: Thu, 21 May 2026 12:26:30 +0200 Subject: [PATCH 14/17] Synchronise IPA documentation with defaults Change-Id: I7b178183132e5dbd77329319d21fbf4ea4c43a9c Signed-off-by: Pierre Riteau --- .../reference/ironic-python-agent.rst | 40 ++++++++++++------- 1 file changed, 25 insertions(+), 15 deletions(-) diff --git a/doc/source/configuration/reference/ironic-python-agent.rst b/doc/source/configuration/reference/ironic-python-agent.rst index 401fa2225..6492bb04e 100644 --- a/doc/source/configuration/reference/ironic-python-agent.rst +++ b/doc/source/configuration/reference/ironic-python-agent.rst @@ -34,6 +34,12 @@ image build``. ``ipa_build_images`` Whether to build IPA images from source. Default is ``False``. +``ipa_build_distro`` + Override the OS distribution used to build IPA images. Default is the host + distribution. +``ipa_build_release`` + Override the OS release used to build IPA images. Default is the host + release. ``ipa_build_source_url`` URL of IPA source repository. Default is https://opendev.org/openstack/ironic-python-agent @@ -43,15 +49,16 @@ image build``. URL of IPA builder source repository. Default is https://opendev.org/openstack/ironic-python-agent-builder ``ipa_builder_source_version`` - Version of IPA builder source repository. Default is ``master``. + Version of IPA builder source repository. Default is ``{{ openstack_branch }}``. ``ipa_build_dib_host_packages_extra`` List of additional build host packages to install. Default is ``[ 'zstd' ]``. ``ipa_build_dib_elements_default`` List of default Diskimage Builder (DIB) elements to use when building IPA - images. Default is ``["centos", "dynamic-login", "enable-serial-console", - "ironic-python-agent-ramdisk"]`` when ``os_distribution`` is ``"rocky"``, and - ``["ubuntu", "dynamic-login", "enable-serial-console", - "ironic-python-agent-ramdisk"]`` otherwise. + images. Default is ``["rocky-container", "dynamic-login", + "enable-serial-console", "ironic-python-agent-ramdisk", "baremetal"]`` when + ``ipa_build_distro`` is ``"rocky"``, and ``[ipa_build_distro, + "dynamic-login", "enable-serial-console", "ironic-python-agent-ramdisk", + "baremetal"]`` otherwise. ``ipa_build_dib_elements_extra`` List of additional Diskimage Builder (DIB) elements to use when building IPA images. Default is empty. @@ -61,14 +68,13 @@ image build``. ``ipa_build_dib_elements_extra``. ``ipa_build_dib_env_default`` Dictionary of default environment variables to provide to Diskimage Builder - (DIB) during IPA image build. Default is ``{"DIB_RELEASE": "9-stream", - "DIB_REPOLOCATION_ironic_python_agent": "{{ ipa_build_source_url }}", - "DIB_REPOREF_ironic_python_agent": "{{ ipa_build_source_version }}", - "DIB_REPOREF_requirements": "{{ ipa_build_source_version }}"}`` if - ``os_distribution`` is ``"rocky"`` else ``{"DIB_RELEASE": "{{ os_release - }}", "DIB_REPOLOCATION_ironic_python_agent": "{{ ipa_build_source_url }}", - "DIB_REPOREF_ironic_python_agent": "{{ ipa_build_source_version }}", - "DIB_REPOREF_requirements": "{{ ipa_build_source_version }}"}``. + (DIB) during IPA image build. Default is ``{"DIB_RELEASE": "{{ + ipa_build_release }}", "DIB_CONTAINERFILE_RUNTIME": "{{ container_engine + }}", "DIB_CONTAINERFILE_RUNTIME_ROOT": "{{ (container_engine == 'podman') | + int }}", "DIB_REPOLOCATION_ironic_python_agent": "{{ ipa_build_source_url + }}", "DIB_REPOREF_ironic_python_agent": "{{ ipa_build_source_version }}", + "DIB_REPOREF_requirements": "{{ ipa_build_source_version }}", + "DIB_IPA_COMPRESS_CMD": 'zstd -19'}`` ``ipa_build_dib_env_extra`` Dictionary of additional environment variables to provide to Diskimage Builder (DIB) during IPA image build. Default is empty. @@ -92,11 +98,15 @@ image build``. role for usage. Default is combination of ``ipa_build_dib_git_elements_default`` and ``ipa_build_dib_git_elements_extra``. ``ipa_build_dib_packages`` - List of DIB packages to install. Default is none. + List of DIB packages to install. Default is ``["python3-yaml"]`` when + ``ipa_build_distro`` is ``"rocky"``, otherwise none. ``ipa_build_upper_constraints_file`` Upper constraints file for installing packages in the virtual environment used for building IPA images. Default is ``{{ pip_upper_constraints_file }}``. +``ipa_build_dib_upper_constraints_file`` + Upper constraints file for installation of DIB to build IPA images. + Default is an empty string. Example: Building IPA images locally ------------------------------------ @@ -304,7 +314,7 @@ inspection. ``ipa_collectors_default`` and ``ipa_collectors_extra``. ``ipa_benchmarks_default`` List of default inspection benchmarks to run. Default is ``["cpu", "disk", - "ram"]``. + "mem"]``. ``ipa_benchmarks_extra`` List of extra inspection benchmarks to run. Default is none. ``ipa_benchmarks`` From 18cc4b921f35aad396e0bd4e198ec45622cf1e5b Mon Sep 17 00:00:00 2001 From: Mark Goddard Date: Mon, 17 Jun 2024 13:53:28 +0100 Subject: [PATCH 15/17] Deploy more containers Extends the seed's "custom containers" feature to support deploying containers on infrastructure VMs, overcloud and Ansible control hosts. Co-Authored-By: Leonie Chamberlin-Medd Change-Id: I19ba61e90c78e088b740feed3dac1f6d1ad262ab Signed-off-by: Pierre Riteau Signed-off-by: Leonie Chamberlin-Medd Signed-off-by: Matt Crees --- .../inventory/group_vars/all/ansible-control | 18 +++ ansible/inventory/group_vars/all/controllers | 18 +++ ansible/inventory/group_vars/all/infra-vms | 18 +++ ansible/inventory/group_vars/all/monitoring | 18 +++ ansible/inventory/group_vars/all/seed | 12 +- ansible/inventory/group_vars/all/storage | 18 +++ .../ansible-control/manage-containers | 10 ++ .../group_vars/controllers/manage-containers | 10 ++ .../group_vars/infra-vms/manage-containers | 10 ++ .../group_vars/monitoring/manage-containers | 10 ++ .../{docker-registry => manage-containers} | 7 +- .../group_vars/storage/manage-containers | 10 ++ ansible/manage-containers.yml | 17 ++ ansible/overcloud-extras.yml | 1 + .../roles/manage-containers/defaults/main.yml | 14 +- .../tasks/deploy-container.yml | 2 +- .../roles/manage-containers/tasks/deploy.yml | 10 +- .../roles/manage-containers/tasks/destroy.yml | 2 +- .../roles/manage-containers/tasks/pull.yml | 9 ++ .../roles/manage-containers/tasks/upgrade.yml | 2 + ansible/seed-manage-containers.yml | 10 -- dev/functions | 9 ++ doc/source/_extra/.htaccess | 4 + doc/source/administration/seed.rst | 2 +- ...m-containers.rst => custom-containers.rst} | 56 +++++-- doc/source/configuration/reference/index.rst | 2 +- doc/source/deployment.rst | 10 +- doc/test/redirect-tests.txt | 3 + etc/kayobe/ansible-control.yml | 18 +++ etc/kayobe/controllers.yml | 18 +++ etc/kayobe/infra-vms.yml | 17 ++ etc/kayobe/monitoring.yml | 17 ++ etc/kayobe/seed.yml | 6 +- etc/kayobe/storage.yml | 17 ++ kayobe/cli/commands.py | 145 ++++++++++++++---- kayobe/tests/unit/cli/test_commands.py | 33 +++- .../overrides.yml.j2 | 6 + .../run.yml | 1 + .../kayobe-overcloud-base/overrides.yml.j2 | 6 + playbooks/kayobe-overcloud-base/run.yml | 7 + ...ploy-more-containers-7799f9cfd98da4f3.yaml | 21 +++ zuul.d/jobs.yaml | 22 +++ zuul.d/project.yaml | 2 + 43 files changed, 570 insertions(+), 78 deletions(-) create mode 100644 ansible/inventory/group_vars/ansible-control/manage-containers create mode 100644 ansible/inventory/group_vars/controllers/manage-containers create mode 100644 ansible/inventory/group_vars/infra-vms/manage-containers create mode 100644 ansible/inventory/group_vars/monitoring/manage-containers rename ansible/inventory/group_vars/seed/{docker-registry => manage-containers} (52%) create mode 100644 ansible/inventory/group_vars/storage/manage-containers create mode 100644 ansible/manage-containers.yml create mode 100644 ansible/roles/manage-containers/tasks/pull.yml create mode 100644 ansible/roles/manage-containers/tasks/upgrade.yml delete mode 100644 ansible/seed-manage-containers.yml rename doc/source/configuration/reference/{seed-custom-containers.rst => custom-containers.rst} (62%) create mode 100644 releasenotes/notes/deploy-more-containers-7799f9cfd98da4f3.yaml diff --git a/ansible/inventory/group_vars/all/ansible-control b/ansible/inventory/group_vars/all/ansible-control index 635024df0..073021253 100644 --- a/ansible/inventory/group_vars/all/ansible-control +++ b/ansible/inventory/group_vars/all/ansible-control @@ -105,6 +105,24 @@ ansible_control_tuned_active_builtin_profile: "throughput-performance" # singleplatform-eng.users role. ansible_control_users: "{{ users_default }}" +############################################################################### +# Ansible control host additional containers configuration + +# Dict of containers to deploy. +# Example: +# ansible_control_containers: +# squid: +# image: "docker.io/stackhpc/squid" +# pre: "{{ kayobe_env_config_path }}/containers/squid/pre.yml" +# post: "{{ kayobe_env_config_path }}/containers/squid/post.yml" +# tag: "3.5.20-1" +# +ansible_control_containers: {} + +# Whether to attempt a basic authentication login to a registry when +# deploying containers. +ansible_control_manage_containers_registry_attempt_login: "{{ kolla_docker_registry_username is truthy and kolla_docker_registry_password is truthy }}" + ############################################################################### # Ansible control host firewalld configuration. diff --git a/ansible/inventory/group_vars/all/controllers b/ansible/inventory/group_vars/all/controllers index f8be1616a..207cbd0d0 100644 --- a/ansible/inventory/group_vars/all/controllers +++ b/ansible/inventory/group_vars/all/controllers @@ -203,6 +203,24 @@ controller_tuned_active_builtin_profile: "throughput-performance" # singleplatform-eng.users role. controller_users: "{{ users_default }}" +############################################################################### +# Controller node additional containers configuration + +# Dict of containers to deploy. +# Example: +# controller_containers: +# squid: +# image: "docker.io/stackhpc/squid" +# pre: "{{ kayobe_env_config_path }}/containers/squid/pre.yml" +# post: "{{ kayobe_env_config_path }}/containers/squid/post.yml" +# tag: "3.5.20-1" +# +controller_containers: {} + +# Whether to attempt a basic authentication login to a registry when +# deploying controller containers +controller_manage_containers_registry_attempt_login: "{{ kolla_docker_registry_username is truthy and kolla_docker_registry_password is truthy }}" + ############################################################################### # Controller node firewalld configuration. diff --git a/ansible/inventory/group_vars/all/infra-vms b/ansible/inventory/group_vars/all/infra-vms index df0b8bcaa..f5643aab1 100644 --- a/ansible/inventory/group_vars/all/infra-vms +++ b/ansible/inventory/group_vars/all/infra-vms @@ -209,6 +209,24 @@ infra_vm_tuned_active_builtin_profile: "virtual-guest" # singleplatform-eng.users role. infra_vm_users: "{{ users_default }}" +############################################################################### +# Infrastructure VM node additional containers configuration + +# Dict of containers to deploy. +# Example: +# infra_vm_containers: +# squid: +# image: "docker.io/stackhpc/squid" +# pre: "{{ kayobe_env_config_path }}/containers/squid/pre.yml" +# post: "{{ kayobe_env_config_path }}/containers/squid/post.yml" +# tag: "3.5.20-1" +# +infra_vm_containers: {} + +# Whether to attempt a basic authentication login to a registry when +# deploying Infrastructure VM node containers +infra_vm_manage_containers_registry_attempt_login: "{{ kolla_docker_registry_username is truthy and kolla_docker_registry_password is truthy }}" + ############################################################################### # Infrastructure VM node firewalld configuration. diff --git a/ansible/inventory/group_vars/all/monitoring b/ansible/inventory/group_vars/all/monitoring index 61492f2b2..396548704 100644 --- a/ansible/inventory/group_vars/all/monitoring +++ b/ansible/inventory/group_vars/all/monitoring @@ -103,6 +103,24 @@ monitoring_tuned_active_builtin_profile: "throughput-performance" # singleplatform-eng.users role. monitoring_users: "{{ controller_users }}" +############################################################################### +# Monitoring node additional containers configuration + +# Dict of containers to deploy. +# Example: +# monitoring_containers: +# squid: +# image: "docker.io/stackhpc/squid" +# pre: "{{ kayobe_env_config_path }}/containers/squid/pre.yml" +# post: "{{ kayobe_env_config_path }}/containers/squid/post.yml" +# tag: "3.5.20-1" +# +monitoring_containers: {} + +# Whether to attempt a basic authentication login to a registry when +# deploying monitoring node containers +monitoring_manage_containers_registry_attempt_login: "{{ kolla_docker_registry_username is truthy and kolla_docker_registry_password is truthy }}" + ############################################################################### # Monitoring node firewalld configuration. diff --git a/ansible/inventory/group_vars/all/seed b/ansible/inventory/group_vars/all/seed index 22c0bc6d4..d5fac0d2a 100644 --- a/ansible/inventory/group_vars/all/seed +++ b/ansible/inventory/group_vars/all/seed @@ -133,7 +133,7 @@ seed_users: "{{ users_default }}" ############################################################################### # Seed node additional containers configuration -# Dict of container images to start +# Dict of containers to deploy. # Example: # seed_containers: # squid: @@ -144,10 +144,16 @@ seed_users: "{{ users_default }}" # seed_containers: {} -# Whether to attempt a basic authentication login to a registry when -# deploying seed containers +# (Deprecated) Whether to attempt a basic authentication login to a registry when +# deploying seed containers. +# TODO(mattcrees): remove seed_deploy_containers_registry_attempt_login in the +# Hibiscus cycle. seed_deploy_containers_registry_attempt_login: "{{ kolla_docker_registry_username is truthy and kolla_docker_registry_password is truthy }}" +# Whether to attempt a basic authentication login to a registry when +# deploying seed containers. +seed_manage_containers_registry_attempt_login: "{{ seed_deploy_containers_registry_attempt_login }}" + ############################################################################### # Seed node firewalld configuration. diff --git a/ansible/inventory/group_vars/all/storage b/ansible/inventory/group_vars/all/storage index 46ea4bc79..a15eafb0b 100644 --- a/ansible/inventory/group_vars/all/storage +++ b/ansible/inventory/group_vars/all/storage @@ -152,6 +152,24 @@ storage_tuned_active_builtin_profile: "throughput-performance" # singleplatform-eng.users role. storage_users: "{{ users_default }}" +############################################################################### +# Storage node additional containers configuration + +# Dict of containers to deploy. +# Example: +# storage_containers: +# squid: +# image: "docker.io/stackhpc/squid" +# pre: "{{ kayobe_env_config_path }}/containers/squid/pre.yml" +# post: "{{ kayobe_env_config_path }}/containers/squid/post.yml" +# tag: "3.5.20-1" +# +storage_containers: {} + +# Whether to attempt a basic authentication login to a registry when +# deploying storage containers +storage_manage_containers_registry_attempt_login: "{{ kolla_docker_registry_username is truthy and kolla_docker_registry_password is truthy }}" + ############################################################################### # Storage node firewalld configuration. diff --git a/ansible/inventory/group_vars/ansible-control/manage-containers b/ansible/inventory/group_vars/ansible-control/manage-containers new file mode 100644 index 000000000..71b0b66d2 --- /dev/null +++ b/ansible/inventory/group_vars/ansible-control/manage-containers @@ -0,0 +1,10 @@ +--- +############################################################################### +# Ansible control host custom containers configuration. + +# Dict of containers to deploy. +manage_custom_containers: "{{ ansible_control_containers }}" + +# Whether to attempt a basic authentication login to a registry when +# deploying Ansible control host containers +manage_containers_registry_attempt_login: "{{ ansible_control_manage_containers_registry_attempt_login }}" diff --git a/ansible/inventory/group_vars/controllers/manage-containers b/ansible/inventory/group_vars/controllers/manage-containers new file mode 100644 index 000000000..370a973a0 --- /dev/null +++ b/ansible/inventory/group_vars/controllers/manage-containers @@ -0,0 +1,10 @@ +--- +############################################################################### +# Controller node custom containers configuration. + +# Dict of containers to deploy. +manage_custom_containers: "{{ controller_containers }}" + +# Whether to attempt a basic authentication login to a registry when +# deploying controller node containers +manage_containers_registry_attempt_login: "{{ controller_manage_containers_registry_attempt_login }}" diff --git a/ansible/inventory/group_vars/infra-vms/manage-containers b/ansible/inventory/group_vars/infra-vms/manage-containers new file mode 100644 index 000000000..d034074f3 --- /dev/null +++ b/ansible/inventory/group_vars/infra-vms/manage-containers @@ -0,0 +1,10 @@ +--- +############################################################################### +# Infrastructure VM node custom containers configuration. + +# Dict of containers to deploy. +manage_custom_containers: "{{ infra_vm_containers }}" + +# Whether to attempt a basic authentication login to a registry when +# deploying infrastructure VM containers +manage_containers_registry_attempt_login: "{{ infra_vm_manage_containers_registry_attempt_login }}" diff --git a/ansible/inventory/group_vars/monitoring/manage-containers b/ansible/inventory/group_vars/monitoring/manage-containers new file mode 100644 index 000000000..d7b840983 --- /dev/null +++ b/ansible/inventory/group_vars/monitoring/manage-containers @@ -0,0 +1,10 @@ +--- +############################################################################### +# Monitoring node custom containers configuration. + +# Dict of containers to deploy. +manage_custom_containers: "{{ monitoring_containers }}" + +# Whether to attempt a basic authentication login to a registry when +# deploying monitoring node containers +manage_containers_registry_attempt_login: "{{ monitoring_manage_containers_registry_attempt_login }}" diff --git a/ansible/inventory/group_vars/seed/docker-registry b/ansible/inventory/group_vars/seed/manage-containers similarity index 52% rename from ansible/inventory/group_vars/seed/docker-registry rename to ansible/inventory/group_vars/seed/manage-containers index f439501ec..9fe2b3449 100644 --- a/ansible/inventory/group_vars/seed/docker-registry +++ b/ansible/inventory/group_vars/seed/manage-containers @@ -1,7 +1,10 @@ --- ############################################################################### -# Seed node docker regsitry configuration. +# Seed node custom containers configuration. + +# Dict of containers to deploy. +manage_custom_containers: "{{ seed_containers }}" # Whether to attempt a basic authentication login to a registry when # deploying seed containers -deploy_containers_registry_attempt_login: "{{ seed_deploy_containers_registry_attempt_login }}" +manage_containers_registry_attempt_login: "{{ seed_manage_containers_registry_attempt_login }}" diff --git a/ansible/inventory/group_vars/storage/manage-containers b/ansible/inventory/group_vars/storage/manage-containers new file mode 100644 index 000000000..ee563f756 --- /dev/null +++ b/ansible/inventory/group_vars/storage/manage-containers @@ -0,0 +1,10 @@ +--- +############################################################################### +# Storage node custom containers configuration. + +# Dict of containers to deploy. +manage_custom_containers: "{{ storage_containers }}" + +# Whether to attempt a basic authentication login to a registry when +# deploying storage node containers +manage_containers_registry_attempt_login: "{{ storage_manage_containers_registry_attempt_login }}" diff --git a/ansible/manage-containers.yml b/ansible/manage-containers.yml new file mode 100644 index 000000000..054034039 --- /dev/null +++ b/ansible/manage-containers.yml @@ -0,0 +1,17 @@ +--- +- name: "Ensure defined container images are {{ kayobe_action | default('deploy') }}ed" + hosts: "{{ manage_containers_target_hosts | default('seed') }}" + tags: + # Kept for backward compatibility. + # TODO(mattcrees): Will be removed in the Hibiscus release. + - seed-deploy-containers + - seed-manage-containers + - manage-containers + tasks: + - import_role: + name: manage-containers + vars: + manage_containers_registry: "{{ kolla_docker_registry }}" + manage_containers_registry_username: "{{ kolla_docker_registry_username }}" + manage_containers_registry_password: "{{ kolla_docker_registry_password }}" + manage_containers_action: "{{ kayobe_action | default('deploy') }}" diff --git a/ansible/overcloud-extras.yml b/ansible/overcloud-extras.yml index 0a5d4fa4e..20af3f179 100644 --- a/ansible/overcloud-extras.yml +++ b/ansible/overcloud-extras.yml @@ -8,4 +8,5 @@ # action: One of deploy, destroy, pull, reconfigure, upgrade - import_playbook: docker-registry.yml +- import_playbook: manage-containers.yml - import_playbook: opensm.yml diff --git a/ansible/roles/manage-containers/defaults/main.yml b/ansible/roles/manage-containers/defaults/main.yml index d98bb77df..e79c8ec75 100644 --- a/ansible/roles/manage-containers/defaults/main.yml +++ b/ansible/roles/manage-containers/defaults/main.yml @@ -2,6 +2,9 @@ # Action to perform: One of: "deploy", "destroy". manage_containers_action: "deploy" +#TODO(mattcrees): remove deploy_containers_defaults in Hibiscus cycle +manage_containers_defaults: "{{ deploy_containers_defaults }}" + deploy_containers_defaults: comparisons: image: strict @@ -13,6 +16,13 @@ deploy_containers_defaults: privileged: False restart_policy: "unless-stopped" -deploy_containers_docker_api_timeout: 120 +manage_custom_containers: [] + +#TODO(mattcrees): remove deploy_containers_docker_api_timeout in Hibiscus cycle. +manage_containers_docker_api_timeout: "{{ deploy_containers_docker_api_timeout | default(120) }}" + +manage_containers_registry: +manage_containers_registry_username: +manage_containers_registry_password: -deploy_containers_registry_attempt_login: "{{ kolla_docker_registry_username is truthy and kolla_docker_registry_password is truthy }}" +manage_containers_registry_attempt_login: "{{ manage_containers_registry_username is truthy and manage_containers_registry_password is truthy }}" diff --git a/ansible/roles/manage-containers/tasks/deploy-container.yml b/ansible/roles/manage-containers/tasks/deploy-container.yml index 2fb39ca90..c29912758 100644 --- a/ansible/roles/manage-containers/tasks/deploy-container.yml +++ b/ansible/roles/manage-containers/tasks/deploy-container.yml @@ -28,7 +28,7 @@ restart_policy: "{{ container_config.restart_policy | default(deploy_containers_defaults.restart_policy) }}" shm_size: "{{ container_config.shm_size | default(omit) }}" sysctls: "{{ container_config.sysctls | default(omit) }}" - timeout: "{{ deploy_containers_docker_api_timeout }}" + timeout: "{{ manage_containers_docker_api_timeout }}" ulimits: "{{ container_config.ulimits | default(omit) }}" user: "{{ container_config.user | default(omit) }}" volumes: "{{ container_config.volumes | default(omit) }}" diff --git a/ansible/roles/manage-containers/tasks/deploy.yml b/ansible/roles/manage-containers/tasks/deploy.yml index a735e9b26..5c9fdfb25 100644 --- a/ansible/roles/manage-containers/tasks/deploy.yml +++ b/ansible/roles/manage-containers/tasks/deploy.yml @@ -1,12 +1,12 @@ --- - name: Login to container registry kayobe_container_login: - registry_url: "{{ kolla_docker_registry or omit }}" - username: "{{ kolla_docker_registry_username }}" - password: "{{ kolla_docker_registry_password }}" + registry_url: "{{ manage_containers_registry or omit }}" + username: "{{ manage_containers_registry_username }}" + password: "{{ manage_containers_registry_password }}" reauthorize: yes when: - - deploy_containers_registry_attempt_login | bool + - manage_containers_registry_attempt_login | bool become: "{{ container_engine == 'podman' }}" - name: Deploy containers (loop) @@ -14,4 +14,4 @@ vars: container_name: "{{ item.key }}" container_config: "{{ item.value }}" - with_dict: "{{ seed_containers }}" + with_dict: "{{ manage_custom_containers }}" diff --git a/ansible/roles/manage-containers/tasks/destroy.yml b/ansible/roles/manage-containers/tasks/destroy.yml index 5059832fa..44613b308 100644 --- a/ansible/roles/manage-containers/tasks/destroy.yml +++ b/ansible/roles/manage-containers/tasks/destroy.yml @@ -4,4 +4,4 @@ vars: container_name: "{{ item.key }}" container_config: "{{ item.value }}" - with_dict: "{{ seed_containers }}" + with_dict: "{{ manage_custom_containers }}" diff --git a/ansible/roles/manage-containers/tasks/pull.yml b/ansible/roles/manage-containers/tasks/pull.yml new file mode 100644 index 000000000..c9f4b474c --- /dev/null +++ b/ansible/roles/manage-containers/tasks/pull.yml @@ -0,0 +1,9 @@ +--- +- name: Pull custom container images + kayobe_container_image: + name: "{{ item.value.image }}" + source: pull + state: present + with_dict: "{{ manage_custom_containers }}" + when: kayobe_action != 'destroy' + become: "{{ container_engine == 'podman' }}" diff --git a/ansible/roles/manage-containers/tasks/upgrade.yml b/ansible/roles/manage-containers/tasks/upgrade.yml new file mode 100644 index 000000000..f670a5b78 --- /dev/null +++ b/ansible/roles/manage-containers/tasks/upgrade.yml @@ -0,0 +1,2 @@ +--- +- include_tasks: deploy.yml diff --git a/ansible/seed-manage-containers.yml b/ansible/seed-manage-containers.yml deleted file mode 100644 index 10cd6c0ab..000000000 --- a/ansible/seed-manage-containers.yml +++ /dev/null @@ -1,10 +0,0 @@ ---- -- name: "Ensure defined container images are {{ kayobe_action | default('deploy') }}ed on seed node" - hosts: seed - tags: - - seed-deploy-containers - - seed-manage-containers - vars: - manage_containers_action: "{{ kayobe_action | default('deploy') }}" - roles: - - role: manage-containers diff --git a/dev/functions b/dev/functions index 27f1924df..1026095e8 100644 --- a/dev/functions +++ b/dev/functions @@ -66,6 +66,9 @@ function config_defaults { # Whether to use Kolla test images. export KAYOBE_USE_KOLLA_TEST_IMAGES=${KAYOBE_USE_KOLLA_TEST_IMAGES:-1} + # Whether to deploy a custom container. + export KAYOBE_DEPLOY_CUSTOM_CONTAINER=${KAYOBE_DEPLOY_CUSTOM_CONTAINER:-0} + # Additional arguments to pass to kayobe commands. export KAYOBE_EXTRA_ARGS=${KAYOBE_EXTRA_ARGS:-} @@ -331,6 +334,12 @@ function ansible_control_host_configure { echo "Configuring the Ansible control host" run_kayobe control host configure + + # Deploy a custom container on the Ansible control host. + if [[ ${KAYOBE_DEPLOY_CUSTOM_CONTAINER} = 1 ]]; then + echo "Deploying custom container" + run_kayobe control host service deploy + fi } function seed_hypervisor_deploy { diff --git a/doc/source/_extra/.htaccess b/doc/source/_extra/.htaccess index b78a9292c..5924e22c5 100644 --- a/doc/source/_extra/.htaccess +++ b/doc/source/_extra/.htaccess @@ -16,3 +16,7 @@ redirectmatch 301 ^/([^/]+/[^/]+)/configuration/seed-custom-containers.html$ /$1 # The following redirects were added when development/* was moved to # contributor/*. redirectmatch 301 ^/([^/]+/[^/]+)/development/([^/]+).html$ /$1/contributor/$2.html + +# The following redirect was added when the seed-custom-containers feature was +# generalised for other hosts. +redirectmatch 301 ^/([^/]+/[^/]+)/configuration/reference/seed-custom-containers.html$ /$1/configuration/reference/custom-containers.html diff --git a/doc/source/administration/seed.rst b/doc/source/administration/seed.rst index 0e2f8ba35..7664305a7 100644 --- a/doc/source/administration/seed.rst +++ b/doc/source/administration/seed.rst @@ -20,7 +20,7 @@ Destroying all services on the seed This step will destroy all containers, container images, and volumes that were deployed by Kayobe and Kolla. To destroy volumes and images associated with - :ref:`custom containers `, you must configure the + :ref:`custom containers `, you must configure the ``post_destroy`` and ``pre_destroy`` hooks to do the clean up manually as Kayobe will not automatically clean these up. It is generally only advised to run this command when you have no important data on the system. diff --git a/doc/source/configuration/reference/seed-custom-containers.rst b/doc/source/configuration/reference/custom-containers.rst similarity index 62% rename from doc/source/configuration/reference/seed-custom-containers.rst rename to doc/source/configuration/reference/custom-containers.rst index 70cc748ca..f0b7a7beb 100644 --- a/doc/source/configuration/reference/seed-custom-containers.rst +++ b/doc/source/configuration/reference/custom-containers.rst @@ -1,11 +1,12 @@ -.. _configuration-seed-custom-containers: +.. _configuration-custom-containers: -====================== -Seed custom containers -====================== +================= +Custom containers +================= This section covers configuration of the user-defined containers deployment -functionality that runs on the seed host. +functionality that runs on the seed, infrastructure VMs, overcloud and Ansible +control hosts. Configuration ============= @@ -70,7 +71,7 @@ Possible options for container deployment: volumes: For a detailed explanation of each option - please see `Ansible -docker_container `_ +docker_container `_ module page. List of Kayobe applied defaults to required docker_container variables: @@ -82,22 +83,47 @@ List of Kayobe applied defaults to required docker_container variables: Docker registry =============== -Seed containers can be pulled from a docker registry deployed on the seed, -since the docker registry deployment step precedes the custom container -deployment step. -It is also possible to deploy a custom containerised docker registry as a -custom seed container. In this case, basic authentication login attempts can be -disabled by setting +Custom containers can be pulled from a docker registry deployed on the seed. +This is possible since the docker registry deployment step precedes the custom +container deployment step. + +It is also possible to deploy a custom containerised docker registry as a custom +seed container. In this case, basic authentication login attempts can be +disabled by setting: .. code-block:: yaml - :caption: ``seed.yml`` + :caption: ``seed.yml`` + + seed_manage_containers_registry_attempt_login: false + +.. code-block:: yaml + :caption: ``infra-vms.yml`` + + infra_vm_manage_containers_registry_attempt_login: false + +.. code-block:: yaml + :caption: ``controllers.yml`` + + controller_manage_containers_registry_attempt_login: false - seed_deploy_containers_registry_attempt_login: false +.. code-block:: yaml + :caption: ``storage.yml`` + + storage_manage_containers_registry_attempt_login: false + +.. code-block:: yaml + :caption: ``monitoring.yml`` + + monitoring_manage_containers_registry_attempt_login: false + +.. code-block:: yaml + :caption: ``ansible-control.yml`` + + ansible_control_manage_containers_registry_attempt_login: false Without this setting, the login will fail because the registry has not yet been deployed. More information on deploying a docker registry can be found :ref:`here `. - diff --git a/doc/source/configuration/reference/index.rst b/doc/source/configuration/reference/index.rst index f88c1f03a..36e39a95e 100644 --- a/doc/source/configuration/reference/index.rst +++ b/doc/source/configuration/reference/index.rst @@ -21,7 +21,7 @@ options. overcloud-dib ironic-python-agent docker-registry - seed-custom-containers + custom-containers infra-vms vgpu nova-cells diff --git a/doc/source/deployment.rst b/doc/source/deployment.rst index c6ec74b7f..eb75d2127 100644 --- a/doc/source/deployment.rst +++ b/doc/source/deployment.rst @@ -229,7 +229,7 @@ After this command has completed the seed services will be active. information about configuring Bifrost. :ref:`configuration-bifrost-overcloud-root-image` provides information on configuring the root disk image build process. See :ref:`here - ` for information about deploying + ` for information about deploying additional, custom services (containers) on a seed node. Building Deployment Images @@ -377,6 +377,11 @@ To trigger the hooks:: (kayobe) $ kayobe infra vm service deploy +.. seealso:: + + See :ref:`here ` for information about + deploying additional, custom services (containers) on infrastructure VMs. + Example ^^^^^^^ @@ -724,6 +729,9 @@ services running in Docker containers. Information on configuration of Kolla Ansible is available :ref:`here `. + See :ref:`here ` for information about + deploying additional, custom services (containers) on overcloud hosts. + Interacting with the Control Plane ---------------------------------- diff --git a/doc/test/redirect-tests.txt b/doc/test/redirect-tests.txt index 0387e3358..a84b8d26e 100644 --- a/doc/test/redirect-tests.txt +++ b/doc/test/redirect-tests.txt @@ -27,3 +27,6 @@ # Moved /kayobe/latest/development/*.html to /kayobe/latest/contributor/ /kayobe/latest/development/automated.html 301 /kayobe/latest/contributor/automated.html /kayobe/latest/development/index.html 301 /kayobe/latest/contributor/index.html + +# Moved /kayobe/latest/configuration/reference/seed-custom-containers.html to /kayobe/latest/configuration/reference/custom-containers.html +/kayobe/latest/configuration/reference/seed-custom-containers.html 301 /kayobe/latest/configuration/reference/custom-containers.html diff --git a/etc/kayobe/ansible-control.yml b/etc/kayobe/ansible-control.yml index 5232d4470..5c3ca32cf 100644 --- a/etc/kayobe/ansible-control.yml +++ b/etc/kayobe/ansible-control.yml @@ -90,6 +90,24 @@ # singleplatform-eng.users role. #ansible_control_users: +############################################################################### +# Ansible control host additional containers configuration + +# Dict of containers to deploy. +# Example: +# seed_containers: +# squid: +# image: "docker.io/stackhpc/squid" +# pre: "{{ kayobe_env_config_path }}/containers/squid/pre.yml" +# post: "{{ kayobe_env_config_path }}/containers/squid/post.yml" +# tag: "3.5.20-1" +# +#ansible_control_containers: + +# Whether to attempt a basic authentication login to a registry when +# deploying containers. +#ansible_control_manage_containers_registry_attempt_login: + ############################################################################### # Ansible control host firewalld configuration. diff --git a/etc/kayobe/controllers.yml b/etc/kayobe/controllers.yml index 7dd3199f2..2f9d3d181 100644 --- a/etc/kayobe/controllers.yml +++ b/etc/kayobe/controllers.yml @@ -164,6 +164,24 @@ # singleplatform-eng.users role. #controller_users: +############################################################################### +# Controller node additional containers configuration + +# Dict of containers to deploy. +# Example: +# controller_containers: +# squid: +# image: "stackhpc/squid:3.5.20-1" +# pre: "{{ kayobe_env_config_path }}/containers/squid/pre.yml" +# post: "{{ kayobe_env_config_path }}/containers/squid/post.yml" +# +#controller_containers: + + +# Whether to attempt a basic authentication login to a registry when +# deploying controller containers +#controller_manage_containers_registry_attempt_login: + ############################################################################### # Controller node firewalld configuration. diff --git a/etc/kayobe/infra-vms.yml b/etc/kayobe/infra-vms.yml index 50362e59d..e8bc24ef0 100644 --- a/etc/kayobe/infra-vms.yml +++ b/etc/kayobe/infra-vms.yml @@ -167,6 +167,23 @@ # singleplatform-eng.users role. #infra_vm_users: +############################################################################### +# Infrastructure VM node additional containers configuration + +# Dict of containers to deploy. +# Example: +# infra_vm_containers: +# squid: +# image: "stackhpc/squid:3.5.20-1" +# pre: "{{ kayobe_env_config_path }}/containers/squid/pre.yml" +# post: "{{ kayobe_env_config_path }}/containers/squid/post.yml" +# +#infra_vm_containers: + +# Whether to attempt a basic authentication login to a registry when +# deploying controller containers +#infra_vm_manage_containers_registry_attempt_login: + ############################################################################### # Infrastructure VM node firewalld configuration. diff --git a/etc/kayobe/monitoring.yml b/etc/kayobe/monitoring.yml index 463b3090b..6045cb20b 100644 --- a/etc/kayobe/monitoring.yml +++ b/etc/kayobe/monitoring.yml @@ -96,6 +96,23 @@ # singleplatform-eng.users role. #monitoring_users: +############################################################################### +# Monitoring node additional containers configuration + +# Dict of containers to deploy. +# Example: +# monitoring_containers: +# squid: +# image: "stackhpc/squid:3.5.20-1" +# pre: "{{ kayobe_env_config_path }}/containers/squid/pre.yml" +# post: "{{ kayobe_env_config_path }}/containers/squid/post.yml" +# +#monitoring_containers: + +# Whether to attempt a basic authentication login to a registry when +# deploying monitoring containers +#monitoring_manage_containers_registry_attempt_login: + ############################################################################### # Monitoring node firewalld configuration. diff --git a/etc/kayobe/seed.yml b/etc/kayobe/seed.yml index 46f1cddc6..044682538 100644 --- a/etc/kayobe/seed.yml +++ b/etc/kayobe/seed.yml @@ -107,7 +107,7 @@ ############################################################################### # Seed node additional containers configuration -# Dict of container images to start +# Dict of containers to deploy. # Example: # seed_containers: # squid: @@ -119,8 +119,8 @@ #seed_containers: # Whether to attempt a basic authentication login to a registry when -# deploying seed containers -#seed_deploy_containers_registry_attempt_login: +# deploying seed containers. +#seed_manage_containers_registry_attempt_login: ############################################################################### # Seed node firewalld configuration. diff --git a/etc/kayobe/storage.yml b/etc/kayobe/storage.yml index 53376b4ef..320ffbb4b 100644 --- a/etc/kayobe/storage.yml +++ b/etc/kayobe/storage.yml @@ -126,6 +126,23 @@ # singleplatform-eng.users role. #storage_users: +############################################################################### +# Storage node additional containers configuration + +# Dict of containers to deploy. +# Example: +# storage_containers: +# squid: +# image: "stackhpc/squid:3.5.20-1" +# pre: "{{ kayobe_env_config_path }}/containers/squid/pre.yml" +# post: "{{ kayobe_env_config_path }}/containers/squid/post.yml" +# +#storage_containers: + +# Whether to attempt a basic authentication login to a registry when +# deploying storage containers +#storage_manage_containers_registry_attempt_login: + ############################################################################### # Storage node firewalld configuration. diff --git a/kayobe/cli/commands.py b/kayobe/cli/commands.py index 2660bd7ad..529d9b623 100644 --- a/kayobe/cli/commands.py +++ b/kayobe/cli/commands.py @@ -466,14 +466,48 @@ class ControlHostServiceDeploy(KayobeAnsibleMixin, VaultMixin, Command): """Deploy the Ansible control host services.""" def take_action(self, parsed_args): - self.app.LOG.debug("Running no-op control host service deploy") + self.app.LOG.debug("Deploying Ansible control host services") + playbooks = _build_playbook_list("manage-containers") + extra_vars = { + "kayobe_action": "deploy", + "manage_containers_target_hosts": "ansible-control", + } + self.run_kayobe_playbooks(parsed_args, playbooks, + limit="ansible-control", + extra_vars=extra_vars) class ControlHostServiceDestroy(KayobeAnsibleMixin, VaultMixin, Command): """Destroy the Ansible control host services.""" def take_action(self, parsed_args): - self.app.LOG.debug("Running no-op control host service destroy") + if not parsed_args.yes_i_really_really_mean_it: + self.app.LOG.error("This will permanently destroy all services " + "and data. Specify " + "--yes-i-really-really-mean-it to confirm that " + "you understand this.") + sys.exit(1) + self.app.LOG.debug("Destroying Ansible control host services") + + extra_vars = { + "kayobe_action": "destroy", + "manage_containers_target_hosts": "ansible-control", + } + playbooks = _build_playbook_list( + "manage-containers", + "docker-registry") + self.run_kayobe_playbooks(parsed_args, playbooks, + limit="ansible-control", + extra_vars=extra_vars) + + def get_parser(self, prog_name): + parser = super(ControlHostServiceDestroy, self).get_parser(prog_name) + group = parser.add_argument_group("Services") + group.add_argument("--yes-i-really-really-mean-it", + action='store_true', + help="confirm that you understand that this will " + "permanently destroy all services and data.") + return parser class ConfigurationDump(KayobeAnsibleMixin, VaultMixin, Command): @@ -883,11 +917,12 @@ class SeedServiceDeploy(KollaAnsibleMixin, KayobeAnsibleMixin, VaultMixin, def take_action(self, parsed_args): self.app.LOG.debug("Deploying seed services") - self.handle_kolla_tags_limits_deprecation(parsed_args) - playbooks = _build_playbook_list( - "seed-manage-containers") - extra_vars = {"kayobe_action": "deploy"} - self.run_kayobe_playbooks(parsed_args, playbooks, + playbooks = _build_playbook_list("manage-containers") + extra_vars = { + "kayobe_action": "deploy", + "manage_containers_target_hosts": "seed", + } + self.run_kayobe_playbooks(parsed_args, playbooks, limit="seed", extra_vars=extra_vars) self.generate_kolla_ansible_config(parsed_args, service_config=False, bifrost_config=True) @@ -925,11 +960,14 @@ def take_action(self, parsed_args): self.run_kolla_ansible_seed(parsed_args, "destroy", extra_args=extra_args) - extra_vars = {"kayobe_action": "destroy"} + extra_vars = { + "kayobe_action": "destroy", + "manage_containers_target_hosts": "seed", + } playbooks = _build_playbook_list( - "seed-manage-containers", + "manage-containers", "docker-registry") - self.run_kayobe_playbooks(parsed_args, playbooks, + self.run_kayobe_playbooks(parsed_args, playbooks, limit="seed", extra_vars=extra_vars) def get_parser(self, prog_name): @@ -960,11 +998,12 @@ class SeedServiceUpgrade(KollaAnsibleMixin, KayobeAnsibleMixin, VaultMixin, def take_action(self, parsed_args): self.app.LOG.debug("Upgrading seed services") - self.handle_kolla_tags_limits_deprecation(parsed_args) - playbooks = _build_playbook_list( - "seed-manage-containers") - extra_vars = {"kayobe_action": "deploy"} - self.run_kayobe_playbooks(parsed_args, playbooks, + playbooks = _build_playbook_list("manage-containers") + extra_vars = { + "kayobe_action": "deploy", + "manage_containers_target_hosts": "seed", + } + self.run_kayobe_playbooks(parsed_args, playbooks, limit="seed", extra_vars=extra_vars) self.generate_kolla_ansible_config(parsed_args, service_config=False, bifrost_config=True) @@ -1219,19 +1258,52 @@ class InfraVMServiceDeploy(KayobeAnsibleMixin, VaultMixin, """Run hooks for infra VM services.""" def take_action(self, parsed_args): - self.app.LOG.debug("Running no-op Infra VM service deploy") + self.app.LOG.debug("Running Infra VM service deploy") + playbooks = _build_playbook_list("manage-containers") + extra_vars = { + "kayobe_action": "deploy", + "manage_containers_target_hosts": "infra-vms", + } + self.run_kayobe_playbooks(parsed_args, playbooks, limit="infra-vms", + extra_vars=extra_vars) -class InfraVMServiceDestroy(KayobeAnsibleMixin, VaultMixin, - Command): +class InfraVMServiceDestroy(KayobeAnsibleMixin, + VaultMixin, Command): """Destroy the infra VM services. Permanently destroy the infra VM containers, container images, and container volumes. """ + def get_parser(self, prog_name): + parser = super(InfraVMServiceDestroy, self).get_parser(prog_name) + group = parser.add_argument_group("Services") + group.add_argument("--yes-i-really-really-mean-it", + action='store_true', + help="confirm that you understand that this will " + "permanently destroy all services and data.") + return parser + def take_action(self, parsed_args): - self.app.LOG.debug("Running no-op Infra VM service destroy") + if not parsed_args.yes_i_really_really_mean_it: + self.app.LOG.error("This will permanently destroy all services " + "and data. Specify " + "--yes-i-really-really-mean-it to confirm that " + "you understand this.") + sys.exit(1) + + self.app.LOG.debug("Destroying infra VM services") + + extra_vars = { + "kayobe_action": "destroy", + "manage_containers_target_hosts": "infra-vms", + } + playbooks = _build_playbook_list( + "manage-containers", + "docker-registry") + self.run_kayobe_playbooks(parsed_args, playbooks, limit="infra-vms", + extra_vars=extra_vars) class OvercloudInventoryDiscover(KayobeAnsibleMixin, VaultMixin, Command): @@ -1712,7 +1784,10 @@ def take_action(self, parsed_args): # Deploy kayobe extra services. playbooks = _build_playbook_list("overcloud-extras") - extra_vars = {"kayobe_action": "deploy"} + extra_vars = { + "kayobe_action": "deploy", + "manage_containers_target_hosts": "overcloud", + } self.run_kayobe_playbooks(parsed_args, playbooks, extra_vars=extra_vars, limit="overcloud") @@ -1771,7 +1846,10 @@ def take_action(self, parsed_args): # Deploy kayobe extra services. playbooks = _build_playbook_list("overcloud-extras") - extra_vars = {"kayobe_action": "deploy"} + extra_vars = { + "kayobe_action": "deploy", + "manage_containers_target_hosts": "overcloud", + } self.run_kayobe_playbooks(parsed_args, playbooks, extra_vars=extra_vars, limit="overcloud") @@ -1868,7 +1946,10 @@ def take_action(self, parsed_args): # Reconfigure kayobe extra services. playbooks = _build_playbook_list("overcloud-extras") - extra_vars = {"kayobe_action": "reconfigure"} + extra_vars = { + "kayobe_action": "reconfigure", + "manage_containers_target_hosts": "overcloud", + } self.run_kayobe_playbooks(parsed_args, playbooks, extra_vars=extra_vars, limit="overcloud") @@ -1923,7 +2004,10 @@ def take_action(self, parsed_args): # Stop kayobe extra services. playbooks = _build_playbook_list("overcloud-extras") - extra_vars = {"kayobe_action": "stop"} + extra_vars = { + "kayobe_action": "stop", + "manage_containers_target_hosts": "overcloud", + } self.run_kayobe_playbooks(parsed_args, playbooks, extra_vars=extra_vars, limit="overcloud") @@ -1975,7 +2059,10 @@ def take_action(self, parsed_args): # Upgrade kayobe extra services. playbooks = _build_playbook_list("overcloud-extras") - extra_vars = {"kayobe_action": "upgrade"} + extra_vars = { + "kayobe_action": "upgrade", + "manage_containers_target_hosts": "overcloud", + } self.run_kayobe_playbooks(parsed_args, playbooks, extra_vars=extra_vars, limit="overcloud") @@ -2026,7 +2113,10 @@ def take_action(self, parsed_args): # Destroy kayobe extra services. playbooks = _build_playbook_list("overcloud-extras") - extra_vars = {"kayobe_action": "destroy"} + extra_vars = { + "kayobe_action": "destroy", + "manage_containers_target_hosts": "overcloud", + } self.run_kayobe_playbooks(parsed_args, playbooks, extra_vars=extra_vars, limit="overcloud") @@ -2048,7 +2138,10 @@ def take_action(self, parsed_args): # Pull container images for kayobe extra services. playbooks = _build_playbook_list("overcloud-extras") - extra_vars = {"kayobe_action": "pull"} + extra_vars = { + "kayobe_action": "pull", + "manage_containers_target_hosts": "overcloud", + } self.run_kayobe_playbooks(parsed_args, playbooks, extra_vars=extra_vars, limit="overcloud") diff --git a/kayobe/tests/unit/cli/test_commands.py b/kayobe/tests/unit/cli/test_commands.py index 694b08c81..171cf4678 100644 --- a/kayobe/tests/unit/cli/test_commands.py +++ b/kayobe/tests/unit/cli/test_commands.py @@ -916,8 +916,10 @@ def test_seed_service_deploy(self, mock_kolla_run, mock_run): expected_calls = [ mock.call( mock.ANY, - [utils.get_data_files_path("ansible", "seed-manage-containers.yml")], # noqa - extra_vars={'kayobe_action': 'deploy'} + [utils.get_data_files_path("ansible", "manage-containers.yml")], # noqa + limit="seed", + extra_vars={'kayobe_action': 'deploy', + 'manage_containers_target_hosts': 'seed'} ), mock.call( mock.ANY, @@ -942,7 +944,8 @@ def test_seed_service_deploy(self, mock_kolla_run, mock_run): utils.get_data_files_path( "ansible", "dell-switch-bmp.yml"), ], - extra_vars={'kayobe_action': 'deploy'} + extra_vars={'kayobe_action': 'deploy', + 'manage_containers_target_hosts': 'seed'} ), ] self.assertListEqual(expected_calls, mock_run.call_args_list) @@ -970,8 +973,10 @@ def test_seed_service_upgrade(self, mock_kolla_run, mock_run): expected_calls = [ mock.call( mock.ANY, - [utils.get_data_files_path("ansible", "seed-manage-containers.yml")], # noqa - extra_vars={'kayobe_action': 'deploy'} + [utils.get_data_files_path("ansible", "manage-containers.yml")], # noqa + limit="seed", + extra_vars={'kayobe_action': 'deploy', + 'manage_containers_target_hosts': 'seed'} ), mock.call( mock.ANY, @@ -1195,7 +1200,7 @@ def test_infra_vm_host_package_update_all(self, mock_run): self.assertListEqual(expected_calls, mock_run.call_args_list) @mock.patch.object(commands.KayobeAnsibleMixin, - "run_kayobe_playbook") + "run_kayobe_playbooks") def test_infra_vm_service_deploy(self, mock_run): command = commands.InfraVMServiceDeploy(TestApp(), []) parser = command.get_parser("test") @@ -1204,7 +1209,16 @@ def test_infra_vm_service_deploy(self, mock_run): result = command.run(parsed_args) self.assertEqual(0, result) - expected_calls = [] + expected_calls = [ + mock.call( + mock.ANY, + [utils.get_data_files_path( + "ansible", "manage-containers.yml")], + limit="infra-vms", + extra_vars={'kayobe_action': 'deploy', + 'manage_containers_target_hosts': 'infra-vms'} + ), + ] self.assertListEqual(expected_calls, mock_run.call_args_list) @mock.patch.object(commands.KayobeAnsibleMixin, @@ -1759,6 +1773,7 @@ def test_overcloud_service_deploy(self, mock_kolla_run, mock_run): limit="overcloud", extra_vars={ "kayobe_action": "deploy", + "manage_containers_target_hosts": "overcloud", }, ), mock.call( @@ -1827,6 +1842,7 @@ def test_overcloud_service_deploy_containers(self, mock_kolla_run, limit="overcloud", extra_vars={ "kayobe_action": "deploy", + "manage_containers_target_hosts": "overcloud", }, ), ] @@ -1924,6 +1940,7 @@ def test_overcloud_service_reconfigure(self, mock_kolla_run, mock_run): limit="overcloud", extra_vars={ "kayobe_action": "reconfigure", + "manage_containers_target_hosts": "overcloud", }, ), mock.call( @@ -1991,6 +2008,7 @@ def test_overcloud_service_stop(self, mock_kolla_run, mock_run): limit="overcloud", extra_vars={ "kayobe_action": "stop", + "manage_containers_target_hosts": "overcloud", }, ), ] @@ -2057,6 +2075,7 @@ def test_overcloud_service_upgrade(self, mock_kolla_run, mock_run): limit="overcloud", extra_vars={ "kayobe_action": "upgrade", + "manage_containers_target_hosts": "overcloud", } ), mock.call( diff --git a/playbooks/kayobe-ansible-control-host-configure-base/overrides.yml.j2 b/playbooks/kayobe-ansible-control-host-configure-base/overrides.yml.j2 index c643dcf6d..34a2faef7 100644 --- a/playbooks/kayobe-ansible-control-host-configure-base/overrides.yml.j2 +++ b/playbooks/kayobe-ansible-control-host-configure-base/overrides.yml.j2 @@ -265,3 +265,9 @@ ansible_control_fail2ban_enabled: true # Add a custom entry to /etc/hosts. custom_etc_hosts_entries: foo.example.com: 127.0.0.88 + +# Deploy a hello-world container. +ansible_control_containers: + hello-world: + image: docker.io/library/hello-world + tag: latest \ No newline at end of file diff --git a/playbooks/kayobe-ansible-control-host-configure-base/run.yml b/playbooks/kayobe-ansible-control-host-configure-base/run.yml index c439f9555..f2c50466e 100644 --- a/playbooks/kayobe-ansible-control-host-configure-base/run.yml +++ b/playbooks/kayobe-ansible-control-host-configure-base/run.yml @@ -2,6 +2,7 @@ - hosts: primary environment: KAYOBE_CONFIG_SOURCE_PATH: "{{ kayobe_config_src_dir }}" + KAYOBE_DEPLOY_CUSTOM_CONTAINER: "{{ deploy_custom_container | default(false) | ternary(1, 0) }}" tasks: - name: Prevent NetworkManager from managing default interface command: 'nmcli dev set {{ ansible_facts.default_ipv4.interface }} managed no' diff --git a/playbooks/kayobe-overcloud-base/overrides.yml.j2 b/playbooks/kayobe-overcloud-base/overrides.yml.j2 index c08a83e5b..913b847e6 100644 --- a/playbooks/kayobe-overcloud-base/overrides.yml.j2 +++ b/playbooks/kayobe-overcloud-base/overrides.yml.j2 @@ -65,3 +65,9 @@ kolla_base_distro: "{% raw %}{{ 'rocky' if os_distribution == 'centos' else os_d # Support overriding container_engine container_engine: "{{ container_engine }}" + +# Deploy a hello-world container. +controller_containers: + hello-world: + image: docker.io/library/hello-world + tag: latest diff --git a/playbooks/kayobe-overcloud-base/run.yml b/playbooks/kayobe-overcloud-base/run.yml index 23ad0ba3d..880b61337 100644 --- a/playbooks/kayobe-overcloud-base/run.yml +++ b/playbooks/kayobe-overcloud-base/run.yml @@ -4,6 +4,7 @@ KAYOBE_CONFIG_SOURCE_PATH: "{{ kayobe_config_src_dir }}" KAYOBE_OVERCLOUD_GENERATE_CERTIFICATES: "{{ tls_enabled | ternary(1, 0) }}" KAYOBE_VAULT_PASSWORD: 'test-password' + KAYOBE_DEPLOY_CUSTOM_CONTAINER: "{{ deploy_custom_container | default(false) | ternary(1, 0) }}" # TODO(mgoddard): Remove this when libvirt on host is used by default. TENKS_CONFIG_PATH: "dev/tenks-deploy-config-compute{% if tls_enabled %}-libvirt-on-host{% endif %}.yml" tasks: @@ -12,6 +13,12 @@ cmd: "{{ kayobe_src_dir }}/dev/overcloud-deploy.sh &> {{ logs_dir }}/ansible/overcloud-deploy" executable: /bin/bash + - name: Check that hello-world custom container was deployed + shell: + cmd: "sudo {{ container_engine | default('docker') }} ps -a | grep hello-world" + executable: /bin/bash + when: deploy_custom_container | default(false) + # Check that passwords are Vault encrypted. - name: View passwords.yml using Ansible Vault vars: diff --git a/releasenotes/notes/deploy-more-containers-7799f9cfd98da4f3.yaml b/releasenotes/notes/deploy-more-containers-7799f9cfd98da4f3.yaml new file mode 100644 index 000000000..97e7e23e0 --- /dev/null +++ b/releasenotes/notes/deploy-more-containers-7799f9cfd98da4f3.yaml @@ -0,0 +1,21 @@ +--- +features: + - | + Extends the seed's "custom containers" feature to support deploying + containers on infrastructure VMs, overcloud and Ansible control hosts. +deprecations: + - | + The tags ``seed-deploy-containers`` and ``seed-manage-containers`` are + deprecated in favour of the more universal ``manage-containers``. They have + been kept for backward compatibility, but will be removed in the Hibiscus + release. + - | + The variable ``seed_deploy_containers_registry_attempt_login`` has + been renamed to ``seed_manage_containers_registry_attempt_login`` and the + deprecated variable will subsequently be removed in the Hibiscus release. + - | + The variables ``deploy_containers_registry_attempt_login`` and + ``deploy_containers_docker_api_timeout`` have been renamed to + ``manage_containers_registry_attempt_login`` and + ``manage_containers_docker_api_timeout`` respectively. The old variable + names are deprecated and will be removed in the Hibiscus release. diff --git a/zuul.d/jobs.yaml b/zuul.d/jobs.yaml index 3157ef5dc..2687d1be0 100644 --- a/zuul.d/jobs.yaml +++ b/zuul.d/jobs.yaml @@ -135,11 +135,31 @@ name: kayobe-ansible-control-host-configure-rocky10 parent: kayobe-ansible-control-host-configure-base nodeset: kayobe-rocky10 + vars: + deploy_custom_container: true + +- job: + name: kayobe-ansible-control-host-configure-rocky10-podman + parent: kayobe-ansible-control-host-configure-base + nodeset: kayobe-rocky10 + vars: + deploy_custom_container: true + container_engine: podman - job: name: kayobe-ansible-control-host-configure-ubuntu-noble parent: kayobe-ansible-control-host-configure-base nodeset: kayobe-ubuntu-noble + vars: + deploy_custom_container: true + +- job: + name: kayobe-ansible-control-host-configure-ubuntu-noble-podman + parent: kayobe-ansible-control-host-configure-base + nodeset: kayobe-ubuntu-noble + vars: + deploy_custom_container: true + container_engine: podman - job: name: kayobe-overcloud-base @@ -348,6 +368,7 @@ vars: fail2ban_enabled: true ci_network_engine: nmstate + deploy_custom_container: true - job: name: kayobe-overcloud-host-configure-ubuntu-noble @@ -355,6 +376,7 @@ nodeset: kayobe-ubuntu-noble vars: fail2ban_enabled: true + deploy_custom_container: true - job: name: kayobe-seed-upgrade-base diff --git a/zuul.d/project.yaml b/zuul.d/project.yaml index e2c6f3e44..6a8217146 100644 --- a/zuul.d/project.yaml +++ b/zuul.d/project.yaml @@ -16,7 +16,9 @@ - kayobe-tox-ansible - kayobe-tox-molecule - kayobe-ansible-control-host-configure-rocky10 + - kayobe-ansible-control-host-configure-rocky10-podman - kayobe-ansible-control-host-configure-ubuntu-noble + - kayobe-ansible-control-host-configure-ubuntu-noble-podman - kayobe-infra-vm-rocky10 - kayobe-infra-vm-ubuntu-noble - kayobe-overcloud-host-configure-rocky10 From c85f3ecbf7da92d4b9b1c855131d725480ce9a74 Mon Sep 17 00:00:00 2001 From: Will Szumski Date: Fri, 24 Apr 2026 17:44:44 +0100 Subject: [PATCH 16/17] [CI] Improve network connectivity check It will now ping between "two" hosts. Since this is an AIO, the same host is added to the ansible inventory twice. This effectively makes the host ping itself. It does mean the task is not skipped. Depends-On: https://review.opendev.org/c/openstack/kayobe-config-dev/+/986140 Change-Id: I33189b5be3e4622fd37ee854410258c1f8d41781 Signed-off-by: Will Szumski --- playbooks/kayobe-base/overrides.yml.j2 | 4 ++++ playbooks/kayobe-overcloud-base/run.yml | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/playbooks/kayobe-base/overrides.yml.j2 b/playbooks/kayobe-base/overrides.yml.j2 index 7ef429669..55ba472d1 100644 --- a/playbooks/kayobe-base/overrides.yml.j2 +++ b/playbooks/kayobe-base/overrides.yml.j2 @@ -1,3 +1,7 @@ --- # Test support for not escalating privileges kayobe_control_host_become: "{{ kayobe_control_host_become }}" + +# Disable external network connectivity check in CI. We see random failures +# pinging 8.8.8.8. +nc_skip_external_net: true diff --git a/playbooks/kayobe-overcloud-base/run.yml b/playbooks/kayobe-overcloud-base/run.yml index 23ad0ba3d..318ddf4e3 100644 --- a/playbooks/kayobe-overcloud-base/run.yml +++ b/playbooks/kayobe-overcloud-base/run.yml @@ -64,7 +64,7 @@ # that aren't deployed in this scenario. cmd: > source {{ kayobe_src_dir }}/dev/environment-setup.sh && - kayobe network connectivity check --limit overcloud + KAYOBE_ENVIRONMENT=aio-network-connectivity kayobe network connectivity check --limit overcloud &> {{ logs_dir }}/ansible/network-connectivity-check executable: /bin/bash - name: Perform database backup From 19fe0d493ea6505b36f2abeddb46f2c5e756fe30 Mon Sep 17 00:00:00 2001 From: Seunghun Lee Date: Fri, 22 May 2026 13:17:10 +0100 Subject: [PATCH 17/17] Fix ansible-collection-kolla not getting installed When ``ansible-galaxy collection install`` is called with two requirements files, only the latter one is registered and dependencies on the first requirements file are ignored. Fixing by performing two separate ansible-galaxy installation. One for core collections (Defined at file path ``kolla_ansible_core_requirements_yml``) and another for additional collections (Defined at file path ``kolla_ansible_requirements_yml``). Closes-Bug: #2153994 Change-Id: Ie179ac46c28c08f3ed41922485ef2e532a2d6e46 Signed-off-by: Seunghun Lee --- ansible/roles/kolla-ansible/tasks/install.yml | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/ansible/roles/kolla-ansible/tasks/install.yml b/ansible/roles/kolla-ansible/tasks/install.yml index 3a77fcc06..9408c3793 100644 --- a/ansible/roles/kolla-ansible/tasks/install.yml +++ b/ansible/roles/kolla-ansible/tasks/install.yml @@ -147,12 +147,25 @@ virtualenv: "{{ kolla_ansible_venv }}" virtualenv_python: "{{ kolla_ansible_venv_python }}" +- name: Ensure core Ansible collections are installed + command: + cmd: >- + ansible-galaxy collection install --force + -r {{ kolla_ansible_core_requirements_yml }} + -p {{ kolla_ansible_venv }}/share/kolla-ansible/ansible/collections/ + environment: + # NOTE(wszumski): Ignore collections shipped with ansible, so that we can install + # newer versions. + ANSIBLE_COLLECTIONS_SCAN_SYS_PATH: "False" + # NOTE(wszumski): Don't use path configured for kayobe + ANSIBLE_COLLECTIONS_PATH: '' + when: not kolla_ansible_venv_ansible + - name: Ensure Ansible collections are installed command: cmd: >- ansible-galaxy collection install --force -r {{ kolla_ansible_requirements_yml }} - {% if not kolla_ansible_venv_ansible %}-r {{ kolla_ansible_core_requirements_yml }}{% endif %} -p {{ kolla_ansible_venv }}/share/kolla-ansible/ansible/collections/ environment: # NOTE(wszumski): Ignore collections shipped with ansible, so that we can install