From 249faa209588bf124879ef270db887986fd96ffd Mon Sep 17 00:00:00 2001 From: Will Szumski Date: Wed, 27 May 2026 17:49:54 +0100 Subject: [PATCH 1/7] CI: Set previous_release for 2026.2 Hibiscus Change-Id: Ibdf02b749d0cff477a1c74b5c538bbec860fc3c5 Signed-off-by: Will Szumski --- zuul.d/jobs.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zuul.d/jobs.yaml b/zuul.d/jobs.yaml index 2687d1be0..fb5f7682a 100644 --- a/zuul.d/jobs.yaml +++ b/zuul.d/jobs.yaml @@ -105,7 +105,7 @@ tenks_src_dir: "{{ ansible_env.PWD ~ '/' ~ zuul.projects['opendev.org/openstack/tenks'].src_dir }}" is_upgrade: "{{ 'upgrade' in zuul.job }}" is_slurp: "{{ 'slurp' in zuul.job }}" - previous_release: "{{ '2025.1' if is_slurp else '2025.2' }}" + previous_release: "{{ '2026.1' if is_slurp else '2026.1' }}" tls_enabled: false fail2ban_enabled: false container_engine: 'docker' From fff2e3728aee469e7e619e3887ea47ad9fb6b2bb Mon Sep 17 00:00:00 2001 From: Takashi Kajinami Date: Wed, 27 May 2026 22:09:04 +0900 Subject: [PATCH 2/7] Remove support for networking-infoblox The project[1] has received no commit for 4 years. Its latest commit still uses upper constraints from the old, abandoned Wallaby branch. [1] https://opendev.org/x/networking-infoblox Depends-on: https://review.opendev.org/c/openstack/kolla-ansible/+/988844 Change-Id: I76178307a82dc723ebe8ca141aa21b1cabcaefbd Signed-off-by: Takashi Kajinami --- ansible/roles/kolla-ansible/templates/kolla/globals.yml | 2 +- ansible/roles/kolla-ansible/templates/overcloud-services.j2 | 3 --- ansible/roles/kolla-ansible/vars/main.yml | 1 - etc/kayobe/kolla.yml | 1 - 4 files changed, 1 insertion(+), 6 deletions(-) diff --git a/ansible/roles/kolla-ansible/templates/kolla/globals.yml b/ansible/roles/kolla-ansible/templates/kolla/globals.yml index 889ba5b49..ce4dd1f76 100644 --- a/ansible/roles/kolla-ansible/templates/kolla/globals.yml +++ b/ansible/roles/kolla-ansible/templates/kolla/globals.yml @@ -120,7 +120,7 @@ docker_registry_username: "{{ kolla_docker_registry_username }}" # Valid options are [ openvswitch, ovn ] neutron_plugin_agent: "{% if kolla_enable_ovn | default(False) | bool %}ovn{% else %}openvswitch{% endif %}" -# Valid options are [ internal, infoblox ] +# Valid option is [ internal ] #neutron_ipam_driver: "internal" # Configure Neutron upgrade option, currently Kolla support diff --git a/ansible/roles/kolla-ansible/templates/overcloud-services.j2 b/ansible/roles/kolla-ansible/templates/overcloud-services.j2 index 4ac3d4b13..86918c095 100644 --- a/ansible/roles/kolla-ansible/templates/overcloud-services.j2 +++ b/ansible/roles/kolla-ansible/templates/overcloud-services.j2 @@ -97,9 +97,6 @@ neutron [neutron-dhcp-agent:children] neutron -[neutron-infoblox-ipam-agent:children] -neutron - [neutron-l3-agent:children] neutron diff --git a/ansible/roles/kolla-ansible/vars/main.yml b/ansible/roles/kolla-ansible/vars/main.yml index d99259b49..c94dbe66e 100644 --- a/ansible/roles/kolla-ansible/vars/main.yml +++ b/ansible/roles/kolla-ansible/vars/main.yml @@ -171,7 +171,6 @@ kolla_feature_flags: - neutron_dvr - neutron_fwaas - neutron_horizon_policy_file - - neutron_infoblox_ipam_agent - neutron_metering - neutron_mlnx - neutron_packet_logging diff --git a/etc/kayobe/kolla.yml b/etc/kayobe/kolla.yml index c5993e8e4..475603327 100644 --- a/etc/kayobe/kolla.yml +++ b/etc/kayobe/kolla.yml @@ -383,7 +383,6 @@ #kolla_enable_neutron_dvr: #kolla_enable_neutron_fwaas: #kolla_enable_neutron_horizon_policy_file: -#kolla_enable_neutron_infoblox_ipam_agent: #kolla_enable_neutron_metering: #kolla_enable_neutron_mlnx: #kolla_enable_neutron_packet_logging: From 444db636625b3ffae1b9cf03045463787fa485a0 Mon Sep 17 00:00:00 2001 From: Leonie Chamberlin-Medd Date: Mon, 1 Jun 2026 14:38:13 +0100 Subject: [PATCH 3/7] Fix naming of custom container variables Updates the custom container example in ansible-control.yml to the correct variable, and updates a description in infra-vms.yml to reference the correct container. Closes-Bug: #2154741 Change-Id: I122af26524197e3d67bbf46a75ff632b836beabe Signed-off-by: Leonie Chamberlin-Medd --- ansible/inventory/group_vars/all/infra-vms | 2 +- etc/kayobe/ansible-control.yml | 2 +- etc/kayobe/infra-vms.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ansible/inventory/group_vars/all/infra-vms b/ansible/inventory/group_vars/all/infra-vms index f5643aab1..848656e7c 100644 --- a/ansible/inventory/group_vars/all/infra-vms +++ b/ansible/inventory/group_vars/all/infra-vms @@ -224,7 +224,7 @@ infra_vm_users: "{{ users_default }}" infra_vm_containers: {} # Whether to attempt a basic authentication login to a registry when -# deploying Infrastructure VM node containers +# 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 }}" ############################################################################### diff --git a/etc/kayobe/ansible-control.yml b/etc/kayobe/ansible-control.yml index 5c3ca32cf..fb1b3fd66 100644 --- a/etc/kayobe/ansible-control.yml +++ b/etc/kayobe/ansible-control.yml @@ -95,7 +95,7 @@ # Dict of containers to deploy. # Example: -# seed_containers: +# ansible_control_containers: # squid: # image: "docker.io/stackhpc/squid" # pre: "{{ kayobe_env_config_path }}/containers/squid/pre.yml" diff --git a/etc/kayobe/infra-vms.yml b/etc/kayobe/infra-vms.yml index e8bc24ef0..806504de3 100644 --- a/etc/kayobe/infra-vms.yml +++ b/etc/kayobe/infra-vms.yml @@ -181,7 +181,7 @@ #infra_vm_containers: # Whether to attempt a basic authentication login to a registry when -# deploying controller containers +# deploying infrastructure VM node containers #infra_vm_manage_containers_registry_attempt_login: ############################################################################### From d7396e066c1d093a2ee5fa573cdbc1557e296af4 Mon Sep 17 00:00:00 2001 From: Will Szumski Date: Thu, 26 Mar 2026 16:18:20 +0000 Subject: [PATCH 4/7] Add context for agents Change-Id: If338782e9bba9a13bf4e7d55c1ddb36130683866 Signed-off-by: Will Szumski --- .agents/scripts/agent-environment.sh | 16 ++ .agents/skills/add-cli-command/SKILL.md | 151 +++++++++++++++ .agents/skills/add-config-variable/SKILL.md | 134 +++++++++++++ .../skills/sync-kolla-feature-flags/SKILL.md | 177 ++++++++++++++++++ .agents/skills/sync-kolla-inventory/SKILL.md | 138 ++++++++++++++ .agents/workdir/.gitkeep | 0 .gitignore | 1 + AGENTS.md | 129 +++++++++++++ 8 files changed, 746 insertions(+) create mode 100644 .agents/scripts/agent-environment.sh create mode 100644 .agents/skills/add-cli-command/SKILL.md create mode 100644 .agents/skills/add-config-variable/SKILL.md create mode 100644 .agents/skills/sync-kolla-feature-flags/SKILL.md create mode 100644 .agents/skills/sync-kolla-inventory/SKILL.md create mode 100644 .agents/workdir/.gitkeep create mode 100644 AGENTS.md diff --git a/.agents/scripts/agent-environment.sh b/.agents/scripts/agent-environment.sh new file mode 100644 index 000000000..95b2e236d --- /dev/null +++ b/.agents/scripts/agent-environment.sh @@ -0,0 +1,16 @@ +#!/bin/bash + +oldstate=$(set +o) + +set -eu +set -o pipefail + +# Resolve the Kayobe checkout root and set the default agent workdir beneath it. + +PARENT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +AGENTS_ROOT="$(dirname "${PARENT}")" +REPO_ROOT="$(dirname "${AGENTS_ROOT}")" + +export KAYOBE_AGENT_WORKDIR="${KAYOBE_AGENT_WORKDIR:-${REPO_ROOT}/.agents/workdir}" + +eval "$oldstate" diff --git a/.agents/skills/add-cli-command/SKILL.md b/.agents/skills/add-cli-command/SKILL.md new file mode 100644 index 000000000..e5533eb47 --- /dev/null +++ b/.agents/skills/add-cli-command/SKILL.md @@ -0,0 +1,151 @@ +--- +name: add-cli-command +description: "Add a new Kayobe CLI command end-to-end. Use when: adding a CLI subcommand, creating a new kayobe command, wiring up a playbook to the CLI. Touches commands.py, setup.cfg, playbook, and unit test." +--- + +# Add a Kayobe CLI Command + +## When to Use + +- Adding a new `kayobe ` command +- Wiring an existing or new Ansible playbook into the CLI + +## Procedure + +### 1. Define the command class in `kayobe/cli/commands.py` + +Choose the right mixin combination: + +| If the command runs... | Inherit from | +|---|---| +| Only Kayobe playbooks | `KayobeAnsibleMixin, VaultMixin, Command` | +| Kayobe + Kolla Ansible | `KollaAnsibleMixin, KayobeAnsibleMixin, VaultMixin, Command` | + +Pattern for Kayobe-only commands: + +```python +class MyNewCommand(KayobeAnsibleMixin, VaultMixin, Command): + """Short description of the command.""" + + def get_parser(self, prog_name): + parser = super(MyNewCommand, self).get_parser(prog_name) + # Add command-specific arguments here if needed + return parser + + def take_action(self, parsed_args): + self.app.LOG.debug("Running my new command") + playbooks = _build_playbook_list("my-new-playbook") + self.run_kayobe_playbooks(parsed_args, playbooks, + limit="target-group") +``` + +Pattern for commands that also invoke Kolla Ansible (inherit `KollaAnsibleMixin`): + +```python +class MyNewKollaCommand(KollaAnsibleMixin, KayobeAnsibleMixin, VaultMixin, Command): + """Short description of the command.""" + + def get_parser(self, prog_name): + parser = super(MyNewKollaCommand, self).get_parser(prog_name) + return parser + + def take_action(self, parsed_args): + self.app.LOG.debug("Running my new kolla command") + self.handle_kolla_tags_limits_deprecation(parsed_args) + playbooks = _build_playbook_list("my-new-playbook") + self.run_kayobe_playbooks(parsed_args, playbooks) + # Run kolla-ansible steps as needed, e.g.: + # self.run_kolla_ansible_overcloud(parsed_args, "deploy") +``` + +`handle_kolla_tags_limits_deprecation(parsed_args)` **must** be called first in +every `KollaAnsibleMixin` command. It enforces warnings and mutual-exclusion +checks for `--kolla-limit`, `--kolla-tags`, and `--kolla-skip-tags`. + +Key helpers: +- `_build_playbook_list("name1", "name2")` builds absolute paths to `ansible/.yml` +- `_get_playbook_path("name")` returns a single playbook path +- Use `ignore_limit=True` for plays that must always run against all hosts (e.g. localhost config generation) +- Use `extra_vars={}` for runtime overrides +- Use `tags=` and `check=False` when needed + +### 2. Register entry points in `setup.cfg` + +Add **two** entries: + +```ini +# Under [entry_points] > kayobe.cli= +my_new_command = kayobe.cli.commands:MyNewCommand + +# Under kayobe.cli.my_new_command = +kayobe.cli.my_new_command = + hooks = kayobe.cli.commands:HookDispatcher +``` + +The entry point name uses underscores and maps to the CLI as `kayobe my new command`. + +### 3. Create the Ansible playbook + +Create `ansible/my-new-playbook.yml` using kebab-case: + +```yaml +--- +- name: Description of what this play does + hosts: target-group + tags: + - my-new-playbook + roles: + - role: my-role +``` + +Keep the playbook minimal. Put logic in a role under `ansible/roles/`. + +### 4. Add a unit test in `kayobe/tests/unit/cli/test_commands.py` + +```python +@mock.patch.object(commands.KayobeAnsibleMixin, + "run_kayobe_playbooks") +def test_my_new_command(self, mock_run): + command = commands.MyNewCommand(TestApp(), []) + parser = command.get_parser("test") + parsed_args = parser.parse_args([]) + result = command.run(parsed_args) + self.assertEqual(0, result) + expected_calls = [ + mock.call( + mock.ANY, + [utils.get_data_files_path("ansible", "my-new-playbook.yml")], + limit="target-group", + ), + ] + self.assertListEqual(expected_calls, mock_run.call_args_list) +``` + +### 5. Add a release note + +```bash +tox -e venv -- reno new add-my-new-command +``` + +Use the `features` section. + +### 6. Update documentation + +Add or update the relevant section in `doc/source/`. + +### 7. Validate + +```bash +tox -e py3 # unit tests pass +tox -e pep8 # style checks pass +``` + +## Checklist + +- [ ] Command class in `kayobe/cli/commands.py` with correct mixins +- [ ] Two `setup.cfg` entry points (command + hook dispatcher) +- [ ] Ansible playbook in `ansible/` (kebab-case) +- [ ] Unit test in `kayobe/tests/unit/cli/test_commands.py` +- [ ] Release note via reno +- [ ] Documentation updated +- [ ] `tox -e py3` and `tox -e pep8` pass diff --git a/.agents/skills/add-config-variable/SKILL.md b/.agents/skills/add-config-variable/SKILL.md new file mode 100644 index 000000000..fd93ded57 --- /dev/null +++ b/.agents/skills/add-config-variable/SKILL.md @@ -0,0 +1,134 @@ +--- +name: add-config-variable +description: "Add a new Kayobe configuration variable with proper inventory defaults, operator examples, and docs. Use when: adding a config knob, introducing a new setting, creating a new component config file. Touches group_vars, etc/kayobe, and doc/source." +--- + +# Add a Kayobe Configuration Variable + +## When to Use + +- Adding a new user-configurable setting +- Introducing a variable for a new or existing component +- Renaming or restructuring existing configuration + +## Procedure + +### 1. Add the inventory default + +Add the variable to the appropriate file under `ansible/inventory/group_vars/`. + +- Global defaults go in `ansible/inventory/group_vars/all/` (extensionless file). +- Group-specific defaults go in `ansible/inventory/group_vars//`. + +**For scalar variables:** + +```yaml +# Description of what this variable controls. Default is . +my_component_setting: "default_value" +``` + +**For list variables, use the three-tier pattern:** + +```yaml +# Combined list of items (do not override directly). +my_component_items: > + {{ my_component_items_default + + my_component_items_extra }} + +# List of default items. +my_component_items_default: + - item1 + - item2 + +# List of extra items added by the operator. +my_component_items_extra: [] +``` + +This lets operators extend defaults via `_extra` without replacing the whole list. + +### 2. Add the commented example in `etc/kayobe/` + +**Only do this for variables that operators are expected to override directly.** +Skip this step for internal defaults — those should remain inventory-only. + +Add a commented-out version in the appropriate `etc/kayobe/` file: + +```yaml +# Description of what this variable controls. Default is . +#my_component_setting: +``` + +For three-tier lists, document all three variables: + +```yaml +# Combined list of items. +#my_component_items: + +# List of default items. +#my_component_items_default: + +# List of extra items added by the operator. +#my_component_items_extra: +``` + +Rules: +- Keep the same comment text as the inventory default (adjusted for operator audience). +- Preserve the `###` section dividers and comment style used in the rest of the file. +- The file name in `etc/kayobe/` should follow the file alignment reference. + +### 3. Update documentation + +Add or update the variable description in the existing authoritative doc page +for the component. Search `doc/source/` to find the right file — do not assume +a filename from the component name. For example: + +- Kolla-ansible settings → `doc/source/configuration/reference/kolla-ansible.rst` +- Kolla settings → `kolla.rst` +- OpenStack/kayobe settings → `doc/source/configuration/reference/kayobe.rst` +- Host-group settings (firewall, sysctl, etc.) → `doc/source/configuration/reference/hosts.rst` +- IPA → `doc/source/configuration/reference/ironic-python-agent.rst` + +When in doubt, `grep -r 'nearby_variable_name' doc/source/` to locate the right page. + +### 4. Add a release note + +```bash +tox -e venv -- reno new add-my-component-setting +``` + +Use the `features` section for new variables, `upgrade` if existing behavior changes. + +### 5. Validate + +```bash +tox -e pep8 # yamllint checks etc/kayobe/ +tox -e ansible-lint # lint the inventory and playbooks +``` + +## File Alignment Reference + +| Inventory defaults | Operator examples | Docs | +|---|---|---| +| `ansible/inventory/group_vars/all/` | `etc/kayobe/.yml` | Find by searching `doc/source/` | +| `ansible/inventory/group_vars//` | `etc/kayobe/.yml` | Same docs file | + +Note: for group-scoped variables the `etc/kayobe/` file is named after the +**group** (e.g. `compute`, `controllers`), not the component file inside +that group. For example `ansible/inventory/group_vars/compute/firewall` +corresponds to `etc/kayobe/compute.yml`. + +## Naming Conventions + +- Prefix variables with the component name: `kolla_`, `compute_`, `seed_`, `dns_`, etc. +- Use `snake_case` for all variable names. +- Use `_default` and `_extra` suffixes for the three-tier list pattern. +- Use `_enabled` (bool) for feature toggles. + +## Checklist + +- [ ] Variable added in `ansible/inventory/group_vars/` with comment and default value +- [ ] Commented example added in `etc/kayobe/.yml` +- [ ] Documentation updated in `doc/source/` +- [ ] Release note via reno +- [ ] `tox -e pep8` passes (yamllint) +- [ ] `tox -e ansible-lint` passes (if touching playbooks or roles) diff --git a/.agents/skills/sync-kolla-feature-flags/SKILL.md b/.agents/skills/sync-kolla-feature-flags/SKILL.md new file mode 100644 index 000000000..b555ccb16 --- /dev/null +++ b/.agents/skills/sync-kolla-feature-flags/SKILL.md @@ -0,0 +1,177 @@ +--- +name: sync-kolla-feature-flags +description: "Synchronise Kayobe Kolla feature flags with a target kolla-ansible tree. Use when: updating for a new OpenStack/Kolla release, refreshing kolla_feature_flags, regenerating etc/kayobe kolla_enable_* examples, and checking removed services in overcloud image regex maps." +--- + +# Sync Kolla Feature Flags + +## When to Use + +- Preparing Kayobe for a new Kolla Ansible release +- Refreshing the canonical `kolla_feature_flags` list +- Regenerating the `kolla_enable_*` commented flags in `etc/kayobe/kolla.yml` +- Verifying removed services are not left behind in inventory defaults + +Last validated for `2026.1`. + +## Procedure + +### 1. Generate the canonical flag list from Kolla Ansible + +Prompt for the target `` (for example `2026.1`), then ensure the +kolla-ansible checkout exists under `${KAYOBE_AGENT_WORKDIR}` in +`kolla-ansible/`. + +Before cloning or reusing the checkout, source `.agents/scripts/agent-environment.sh` to +set `KAYOBE_AGENT_WORKDIR`. + +If `kolla-ansible/` does not exist, clone with: + +```bash +source .agents/scripts/agent-environment.sh +git clone https://github.com/openstack/kolla-ansible -b stable/ "${KAYOBE_AGENT_WORKDIR}/kolla-ansible" +``` + +If `kolla-ansible/` already exists, checkout the correct branch: + +```bash +source .agents/scripts/agent-environment.sh +git -C "${KAYOBE_AGENT_WORKDIR}/kolla-ansible" status --porcelain +``` + +If this command returns any output, stop and ask the user to clean, commit, or +stash changes before continuing. Abort all sync checks until the checkout is +clean. + +Then run: + +```bash +source .agents/scripts/agent-environment.sh +git -C "${KAYOBE_AGENT_WORKDIR}/kolla-ansible" fetch origin +git -C "${KAYOBE_AGENT_WORKDIR}/kolla-ansible" checkout stable/ +git -C "${KAYOBE_AGENT_WORKDIR}/kolla-ansible" pull --ff-only origin stable/ +``` + +Then run: + +```bash +source .agents/scripts/agent-environment.sh +tools/kolla-feature-flags.sh "${KAYOBE_AGENT_WORKDIR}/kolla-ansible" +``` + +The script output is the canonical sorted list for +`ansible/roles/kolla-ansible/vars/main.yml`. + +### 2. Update `kolla_feature_flags` + +Replace the `kolla_feature_flags` list in +`ansible/roles/kolla-ansible/vars/main.yml` with the script output from step 1. + +### 3. Regenerate `kolla_enable_*` examples + +Run: + +```bash +tools/feature-flags.py +``` + +Copy the script output and replace the `kolla_enable_*` commented flag block in +`etc/kayobe/kolla.yml`. + +### 4. Apply repository guardrails learned from prior syncs + +After syncing, verify that removed services are consistently absent from all +Kayobe-owned locations. Run `git grep ` to find any stragglers. + +#### `ansible/inventory/group_vars/all/kolla` + +- No removed-service entries in `overcloud_container_image_regex_map`. +- No removed-service `kolla_enable_*` defaults. +- No stale dependencies on a removed service (e.g. `kolla_enable_placement` + previously depended on `kolla_enable_zun`; remove such references). + +#### `etc/kayobe/kolla.yml` + +- No commented `#kolla_enable_:` or `#kolla_enable_horizon_:` + entries for removed services. + +#### `ansible/roles/kolla-openstack/defaults/main.yml` + +- No removed-service include globs in + `kolla_openstack_custom_config_include_globs_default`. +- No removed-service template override rules in + `kolla_openstack_custom_config_rules_default`. +- No `kolla_enable_` default variable block for removed services. + +#### `doc/source/configuration/reference/kolla-ansible.rst` + +- No removed-service rows in the custom config path table. + +#### `ansible/roles/kolla-ansible/defaults/main.yml` + +- No commented `#kolla_enable_:` entries for removed services. + +#### `ansible/roles/kolla-ansible/templates/kolla/globals.yml` + +- No commented or active removed-service-specific globals + (e.g. `#docker_configure_for_zun`). + +#### `ansible/roles/kolla-ansible/templates/overcloud-components.j2` + +- No `[:children]` group entries for removed services. +- New top-level services (not sub-exporters/sub-services of an existing + component) need a `[:children]` entry here. Check the kolla-ansible + source inventory for guidance on whether a new flag warrants a component + group. + +#### `ansible/roles/kolla-ansible/templates/overcloud-services.j2` + +- No `[-*:children]` group entries or `` child group + references for removed services. +- New services need appropriate `[-*:children]` entries here. Each + container defined by kolla-ansible for the service typically needs one. + Sub-exporters/sub-services of an existing component (e.g. + `prometheus-openstack-network-exporter`, `prometheus-valkey-exporter`) go + here only, not in `overcloud-components.j2`. + +#### `ansible/container-engine.yml` + +- No playbook vars that reference removed-service feature flags + (e.g. `docker_configure_for_zun: "{{ kolla_enable_zun | bool }}"`). + +#### `ansible/roles/kolla-ansible/tests/test-extras.yml` + +- No `kolla_enable_: True` entries in the "enable everything" block. +- No `#enable_: True` entries in the commented expected-variables + block. + +Known removed-service examples include: `influxdb`, `kuryr`, `telegraf`, `zun`. + +### 5. Optional template sanity check + +A prior scan found no removable removed-service-specific files under: + +- `ansible/roles/kolla-openstack/templates/kolla/config` + +Use this as a reference point when deciding whether template deletions are +needed during future syncs. + +## Checklist + +- [ ] Prompted for target `` +- [ ] Ensured `kolla-ansible/` exists in repo root on `stable/` +- [ ] Confirmed `kolla-ansible/` has no uncommitted changes before checkout +- [ ] Aborted all sync checks if `kolla-ansible/` was dirty +- [ ] Ran `tools/kolla-feature-flags.sh ` +- [ ] Updated `ansible/roles/kolla-ansible/vars/main.yml` +- [ ] Ran `tools/feature-flags.py` +- [ ] Updated `etc/kayobe/kolla.yml` `kolla_enable_*` block +- [ ] Confirmed removed services absent from `ansible/inventory/group_vars/all/kolla` +- [ ] Confirmed removed services absent from `ansible/roles/kolla-ansible/defaults/main.yml` +- [ ] Confirmed removed services absent from `ansible/roles/kolla-ansible/templates/kolla/globals.yml` +- [ ] Confirmed removed services absent from `ansible/roles/kolla-ansible/templates/overcloud-components.j2` +- [ ] Confirmed removed services absent from `ansible/roles/kolla-ansible/templates/overcloud-services.j2` +- [ ] Confirmed removed services absent from `ansible/container-engine.yml` +- [ ] Confirmed removed services absent from `ansible/roles/kolla-ansible/tests/test-extras.yml` +- [ ] Confirmed removed services absent from `ansible/roles/kolla-openstack/defaults/main.yml` +- [ ] Confirmed removed services absent from `doc/source/configuration/reference/kolla-ansible.rst` diff --git a/.agents/skills/sync-kolla-inventory/SKILL.md b/.agents/skills/sync-kolla-inventory/SKILL.md new file mode 100644 index 000000000..5201b7881 --- /dev/null +++ b/.agents/skills/sync-kolla-inventory/SKILL.md @@ -0,0 +1,138 @@ +--- +name: sync-kolla-inventory +description: "Synchronise Kayobe overcloud inventory templates with Kolla Ansible multinode inventory. Use when: updating for a new OpenStack/Kolla release, copying inventory group changes from kolla-ansible, and validating top-level/components/services split in Kayobe templates." +--- + +# Sync Kolla Inventory + +## When to Use + +- Preparing Kayobe for a new Kolla Ansible release +- Syncing inventory changes from kolla-ansible multinode inventory +- Verifying new/removed inventory groups are reflected in the correct Kayobe + template + +Last validated for `2026.1`. + +## Source and Targets + +- Source inventory in kolla-ansible: + - `ansible/inventory/multinode` +- Kayobe targets: + - `ansible/roles/kolla-ansible/templates/overcloud-top-level.j2` + - `ansible/roles/kolla-ansible/templates/overcloud-components.j2` + - `ansible/roles/kolla-ansible/templates/overcloud-services.j2` + +Kayobe splits multinode inventory into three parts. + +## Boundary Rules + +### Top level + +Target: `ansible/roles/kolla-ansible/templates/overcloud-top-level.j2` + +- This file is heavily templated and does not typically need changes. +- Look for changes in multinode before the `[baremetal]` group. +- If there are changes in that region, port them carefully while preserving + existing Kayobe templating. + +### Components + +Target: `ansible/roles/kolla-ansible/templates/overcloud-components.j2` + +- Includes multinode groups from `[baremetal]` down to this marker: + +```text +# Additional control implemented here. These groups allow you to control which +# services run on which hosts at a per-service level. +``` + +- This file maps components to top-level groups. + +### Services + +Target: `ansible/roles/kolla-ansible/templates/overcloud-services.j2` + +- Includes multinode groups from the marker above to end of file. +- This file maps service containers to components. +- Keep Kayobe-specific small changes in this section unless intentionally + removed. + +## Procedure + +### 1. Get the source inventory snapshot + +Prompt for the target `` (for example `2026.1`), then ensure the +kolla-ansible checkout exists under `${KAYOBE_AGENT_WORKDIR}` in +`kolla-ansible/`. + +Before cloning or reusing the checkout, source `.agents/scripts/agent-environment.sh` to set +`KAYOBE_AGENT_WORKDIR`. + +If `kolla-ansible/` does not exist, clone with: + +```bash +source .agents/scripts/agent-environment.sh +git clone https://github.com/openstack/kolla-ansible -b stable/ "${KAYOBE_AGENT_WORKDIR}/kolla-ansible" +``` + +If `kolla-ansible/` already exists, checkout the correct branch: + +```bash +source .agents/scripts/agent-environment.sh +git -C "${KAYOBE_AGENT_WORKDIR}/kolla-ansible" status --porcelain +``` + +If this command returns any output, stop and ask the user to clean, commit, or +stash changes before continuing. Abort all sync checks until the checkout is +clean. + +Then run: + +```bash +source .agents/scripts/agent-environment.sh +git -C "${KAYOBE_AGENT_WORKDIR}/kolla-ansible" fetch origin +git -C "${KAYOBE_AGENT_WORKDIR}/kolla-ansible" checkout stable/ +git -C "${KAYOBE_AGENT_WORKDIR}/kolla-ansible" pull --ff-only origin stable/ +``` + +### 2. Compare multinode against Kayobe split templates + +Review group additions/removals/renames in the source and map each change by +section boundary: + +- Before `[baremetal]` -> `overcloud-top-level.j2` +- `[baremetal]` to marker -> `overcloud-components.j2` +- Marker to end -> `overcloud-services.j2` + +### 3. Apply updates to the correct Kayobe template + +Port each relevant change into the appropriate file while preserving existing +Kayobe templating and comments. + +### 4. Validate new services are placed correctly + +When new services appear in multinode: + +- Add top-level component groups to `overcloud-components.j2` when appropriate. +- Add per-service container groups to `overcloud-services.j2`. +- Sub-services/exporters of an existing component generally belong in + `overcloud-services.j2` only. + +### 5. Re-check Kayobe-specific behavior + +After sync, confirm intentional Kayobe differences are still present and valid, +particularly in `overcloud-services.j2`. + +## Checklist + +- [ ] Prompted for target `` +- [ ] Ensured `kolla-ansible/` exists in repo root on `stable/` +- [ ] Confirmed `kolla-ansible/` has no uncommitted changes before checkout +- [ ] Aborted all sync checks if `kolla-ansible/` was dirty +- [ ] Compared kolla-ansible `ansible/inventory/multinode` with Kayobe templates +- [ ] Reviewed pre-`[baremetal]` changes for `overcloud-top-level.j2` +- [ ] Synced component groups into `overcloud-components.j2` +- [ ] Synced service groups into `overcloud-services.j2` +- [ ] Verified new services are in the correct file(s) +- [ ] Preserved intentional Kayobe-specific service-section changes diff --git a/.agents/workdir/.gitkeep b/.agents/workdir/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/.gitignore b/.gitignore index edc6eab5a..6b46a460c 100644 --- a/.gitignore +++ b/.gitignore @@ -65,6 +65,7 @@ ansible/collections/ # Virtualenvs ansible/kolla-venv/ venvs +.agents/workdir/ # Vagrant .vagrant diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 000000000..294a0c8a5 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,129 @@ +# AGENTS.md + +Guidance for coding agents working in this repository. + +## Scope + +These instructions apply to the whole repository. + +## Repository Overview + +Kayobe is an OpenStack project for deploying containerised OpenStack to bare metal. The repository combines: + +- Python application code in `kayobe/` +- Ansible playbooks, plugins, and inventory defaults in `ansible/` +- Ansible roles used by Kayobe in `ansible/roles/` +- Top-level CI-oriented roles in `roles/`, used by Zuul jobs +- Example operator configuration in `etc/kayobe/` +- Documentation in `doc/source/` + +When changing behavior, prefer to preserve the existing split between code, default inventory values, and operator-facing example configuration. + +## Core Conventions + +### Python + +- Follow PEP 8 style for Python, along with the OpenStack Style Commandments referenced in `HACKING.rst`. +- Use the existing Apache 2.0 file header for new Python files. +- Keep imports grouped as standard library, third-party, then local imports. +- Use module-level logging with `LOG = logging.getLogger(__name__)`. +- Raise project exceptions from `kayobe.exception.KayobeException` or a specific subclass. +- Follow existing Cliff command patterns in `kayobe/cli/commands.py`: + - mixins provide shared parser and execution behavior + - command classes implement `get_parser()` and `take_action()` or `run()` consistently with nearby code + - CLI naming is driven by `setup.cfg` entry points + +### Ansible + +- Keep top-level playbooks in `ansible/` minimal. Put reusable logic in roles. +- Use kebab-case names for playbooks in `ansible/`. +- Preserve the current YAML style and comment formatting in inventory defaults and example config. +- Custom Ansible plugins live in `ansible/action_plugins/`, `ansible/filter_plugins/`, `ansible/lookup_plugins/`, and `ansible/test_plugins/`. +- For **filter and lookup plugins**, implementations live in `kayobe/plugins/` with thin re-export wrappers in the `ansible/*_plugins/` directories. Put new filter/lookup logic in `kayobe/plugins/` and add a wrapper under `ansible/*_plugins/` if following this pattern. +- For **action plugins**, implementations are typically full standalone modules directly in `ansible/action_plugins/` with no counterpart in `kayobe/plugins/`. Follow the nearest existing plugin of the same kind. +- Roles use standard Ansible layout such as `defaults/main.yml`, `tasks/main.yml`, and `vars/main.yml`. +- Put roles used by Kayobe playbooks under `ansible/roles/`. +- Treat the top-level `roles/` directory as Zuul/CI-focused content rather than the main home for Kayobe runtime roles. +- For list-type variables, follow the three-tier composition pattern where applicable: `_default` + `_extra` combined into ``. This lets operators extend defaults without replacing them. + +### Inventory Defaults And Example Config + +- Inventory defaults in `ansible/inventory/group_vars/` are commonly stored in extensionless files, for example `ansible/inventory/group_vars/all/kolla`. +- Operator-facing example configuration lives in `etc/kayobe/*.yml` and typically contains commented-out variables with explanatory text. +- If you add or rename a variable in `ansible/inventory/group_vars//` or `ansible/inventory/group_vars/all/`, also add or update the corresponding commented example in `etc/kayobe/.yml` when that file represents the same component. +- The component file name should usually stay aligned across these locations, for example inventory defaults in `.../kolla` and example configuration in `etc/kayobe/kolla.yml`. +- Keep user-overridable values documented in `etc/kayobe/` rather than only discoverable from inventory defaults. + +### Testing + +- Unit tests live in `kayobe/tests/unit/`, mirroring the module structure. +- Use `unittest.TestCase` with `self.maxDiff = None`. +- Mock external calls with `@mock.patch.object(..., autospec=True)`. +- CLI command tests instantiate the command class with a test app, parse arguments, call `run()`, and assert the expected playbook calls via `mock_run.call_args_list`. +- Molecule tests for roles live in `ansible/roles//molecule/` and use testinfra for verification. +- Shared molecule helpers are in `kayobe/tests/molecule/utils.py`. + +### Documentation + +- Update documentation when behavior, configuration, or workflows change. +- For any non-trivial change, add or update the relevant documentation in `doc/source/`. +- Prefer `doc/source/` for contributor or user-facing changes, and keep wording consistent with the existing docs. + +### Commit Messages + +- Use the 50/72 rule: subject line ≤ 50 characters, body lines wrapped at 72 characters. +- Write the subject in the imperative mood (e.g. "Fix broken conditional" not "Fixed broken conditional"). +- Separate the subject from the body with a blank line. +- Use the body to explain *what* and *why*, not *how*. +- A `Change-Id` trailer is added automatically by a git hook. Always preserve it when amending a commit. +- Reference bugs with a `Closes-Bug: #` trailer (Launchpad) or `Related-Bug: #` if the commit does not fully fix the bug. + +### Release Notes + +- Kayobe uses `reno` for release notes, stored in `releasenotes/notes/`. +- Default to adding a release note for code, behavior, configuration, and other user-visible changes. +- Docs-only, CI-only, and `TrivialFix` changes generally should not add a release note. +- Create new release notes with `tox -e venv -- reno new `. +- Use an appropriate section such as `features`, `fixes`, `upgrade`, or `deprecations`, following the templates in `releasenotes/templates/`. + +## Validation + +Use the narrowest relevant validation for the change you make. +Follow the validation workflow defined in `tox.ini`, and treat issues reported by the tools run via `tox` as authoritative for the checks they perform. + +- Python tests: `tox -e py3` +- Python style, lint, and static checks: `tox -e pep8` +- Ansible checks: `tox -e ansible-lint` +- Ansible syntax checks: `tox -e ansible-syntax` +- Role/integration checks: `tox -e molecule` + +If a change touches Ansible inventory defaults or example config, at minimum run the relevant lint or syntax validation when feasible. +For Python changes, run `tox -e pep8` as a mandatory local style check when the environment permits running repository validation. + +## Working Rules For Agents + +- Do not modify any files not tracked by git unless explicitly instructed to or when creating a new file. +- When skills need temporary files or external checkouts, always source `source .agents/scripts/agent-environment.sh` before running shell commands. +- `KAYOBE_AGENT_WORKDIR` is set by `.agents/scripts/agent-environment.sh` and defaults to `.agents/workdir/` under the Kayobe checkout root. +- Override it by setting `KAYOBE_AGENT_WORKDIR` explicitly. +- Read nearby files before making structural changes; patterns in this repo are deliberate and often repeated. +- If repository tooling does not fully determine style or structure, follow nearby files and existing project patterns. +- Prefer focused changes over refactors. +- Do not remove comments from `etc/kayobe/*.yml` unless they are being replaced with better operator guidance. +- Do not put secrets or site-specific values into repository defaults. +- Respect existing user changes in the worktree and avoid reverting unrelated files. +- When adding new configuration knobs, check all three places as applicable: + - inventory defaults in `ansible/inventory/group_vars/` + - operator example config in `etc/kayobe/` + - documentation in `doc/source/` + +## Useful References + +- `README.rst` +- `HACKING.rst` +- `CONTRIBUTING.rst` +- `setup.cfg` +- `tox.ini` +- `kayobe/cli/commands.py` +- `ansible/inventory/group_vars/all/` +- `etc/kayobe/` From 99fe27b86535a635e042b433a5537503bfc230db Mon Sep 17 00:00:00 2001 From: Will Szumski Date: Fri, 29 May 2026 18:43:12 +0100 Subject: [PATCH 5/7] Use per-host XDG cache for baremetal registration Concurrent registration of baremetal compute nodes triggers: [Errno 11] Resource temporarily unavailable Using a seperate cache directory per node prevents these conflicts. This is also being tracked as a python-ironicclient bug[1]. We can remove this workaround if this issue is resolved within the client. [1] https://bugs.launchpad.net/python-ironicclient/+bug/2154729 Closes-Bug: #2154810 Change-Id: I659847a02b3fdb672c7f9d38280c6145d483d774 Signed-off-by: Will Szumski --- ansible/baremetal-compute-register.yml | 7 ++++++- ansible/overcloud-hardware-register.yml | 4 ++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/ansible/baremetal-compute-register.yml b/ansible/baremetal-compute-register.yml index 2ce507e19..009f66a2c 100644 --- a/ansible/baremetal-compute-register.yml +++ b/ansible/baremetal-compute-register.yml @@ -28,6 +28,7 @@ vars: venv: "{{ virtualenv_path }}/openstack-cli" controller_host: "{{ groups['controllers'][0] }}" + openstack_cli_cache_home: "{{ hostvars[controller_host].ansible_facts.env.HOME }}/.cache/kayobe-openstack-{{ inventory_hostname }}" tasks: - name: Check Ironic variables are defined ansible.builtin.assert: @@ -80,4 +81,8 @@ # NOTE: Without this, the controller's ansible_host variable will not # be respected when using delegate_to. ansible_host: "{{ hostvars[controller_host].ansible_host | default(controller_host) }}" - environment: "{{ openstack_auth_env }}" + # Avoid concurrent access to python-ironicclient dbm cache when + # registration tasks are delegated to a single controller. + environment: >- + {{ openstack_auth_env | + combine({'XDG_CACHE_HOME': openstack_cli_cache_home}) }} diff --git a/ansible/overcloud-hardware-register.yml b/ansible/overcloud-hardware-register.yml index 13c9c812d..32902256a 100644 --- a/ansible/overcloud-hardware-register.yml +++ b/ansible/overcloud-hardware-register.yml @@ -4,6 +4,7 @@ gather_facts: false vars: seed_host: "{{ groups['seed'][0] }}" + openstack_cli_cache_home: "~/.cache/kayobe-openstack-{{ inventory_hostname }}" # Try to reduce contention on Bifrost and resolve db lock errors serial: 10 tasks: @@ -18,6 +19,7 @@ {{ container_engine }} exec bifrost_deploy bash -c ' export OS_CLOUD=bifrost && + export XDG_CACHE_HOME={{ openstack_cli_cache_home }} && openstack baremetal node show {{ inventory_hostname }}' register: node_show failed_when: false @@ -31,6 +33,7 @@ {{ container_engine }} exec bifrost_deploy bash -c ' export OS_CLOUD=bifrost && + export XDG_CACHE_HOME={{ openstack_cli_cache_home }} && openstack baremetal node create --driver {{ ironic_driver }} {% for key, value in ironic_driver_info.items() %} @@ -51,6 +54,7 @@ {{ container_engine }} exec bifrost_deploy bash -c ' export OS_CLOUD=bifrost && + export XDG_CACHE_HOME={{ openstack_cli_cache_home }} && openstack baremetal node manage {{ inventory_hostname }} --wait' From d564feffded2fbb42efbe2626e618e3f232b0791 Mon Sep 17 00:00:00 2001 From: Pierre Riteau Date: Wed, 3 Jun 2026 22:58:01 +0200 Subject: [PATCH 6/7] CI: Stop using image from Docker Hub Some CI jobs are hitting rate limits. Change-Id: Iad22b28c39a023d26f89b753af73dd730d000cea Signed-off-by: Pierre Riteau --- .../overrides.yml.j2 | 8 ++++---- playbooks/kayobe-overcloud-base/overrides.yml.j2 | 8 ++++---- playbooks/kayobe-overcloud-base/run.yml | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) 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 34a2faef7..a5940cabd 100644 --- a/playbooks/kayobe-ansible-control-host-configure-base/overrides.yml.j2 +++ b/playbooks/kayobe-ansible-control-host-configure-base/overrides.yml.j2 @@ -266,8 +266,8 @@ ansible_control_fail2ban_enabled: true custom_etc_hosts_entries: foo.example.com: 127.0.0.88 -# Deploy a hello-world container. +# Deploy a test container. ansible_control_containers: - hello-world: - image: docker.io/library/hello-world - tag: latest \ No newline at end of file + node_exporter: + image: "quay.io/prometheus/node-exporter" + tag: "latest" diff --git a/playbooks/kayobe-overcloud-base/overrides.yml.j2 b/playbooks/kayobe-overcloud-base/overrides.yml.j2 index 913b847e6..72eeb2018 100644 --- a/playbooks/kayobe-overcloud-base/overrides.yml.j2 +++ b/playbooks/kayobe-overcloud-base/overrides.yml.j2 @@ -66,8 +66,8 @@ 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. +# Deploy a test container. controller_containers: - hello-world: - image: docker.io/library/hello-world - tag: latest + node_exporter: + image: "quay.io/prometheus/node-exporter" + tag: "latest" diff --git a/playbooks/kayobe-overcloud-base/run.yml b/playbooks/kayobe-overcloud-base/run.yml index 0c7820d5c..9fcb2da17 100644 --- a/playbooks/kayobe-overcloud-base/run.yml +++ b/playbooks/kayobe-overcloud-base/run.yml @@ -15,7 +15,7 @@ - name: Check that hello-world custom container was deployed shell: - cmd: "sudo {{ container_engine | default('docker') }} ps -a | grep hello-world" + cmd: "sudo {{ container_engine | default('docker') }} ps -a | grep node-exporter" executable: /bin/bash when: deploy_custom_container | default(false) From 0e1fab73cd9b45b5e317f8fddb729d1a6896656a Mon Sep 17 00:00:00 2001 From: Pierre Riteau Date: Wed, 3 Jun 2026 23:15:58 +0200 Subject: [PATCH 7/7] Replace `which` with `command` `command` is a builtin command in any POSIX-compatible shell, while `which` is an extra package which can be absent. Change-Id: I8a1f505e17fa282d9eb3c76cb703b84b322b3dbb Signed-off-by: Pierre Riteau --- dev/functions | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dev/functions b/dev/functions index 547965730..4c0ebb47d 100644 --- a/dev/functions +++ b/dev/functions @@ -139,7 +139,7 @@ function config_init { function is_dnf { if [[ -e /etc/centos-release || -e /etc/rocky-release ]]; then - /usr/bin/which dnf >/dev/null 2>&1 + command -v dnf >/dev/null 2>&1 else return 1 fi @@ -147,7 +147,7 @@ function is_dnf { function is_yum { if [[ -e /etc/centos-release || -e /etc/rocky-release ]]; then - /usr/bin/which yum >/dev/null 2>&1 + command -v yum >/dev/null 2>&1 else return 1 fi