Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions ansible/inventory/group_vars/all/globals
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
###############################################################################
# Local path configuration (Ansible control host).

# Path to Kayobe data files
kayobe_path: "{{ lookup('cached', 'kayobe_path') }}"

# Path to Kayobe configuration directory on Ansible control host.
kayobe_config_path: "{{ lookup('env', 'KAYOBE_CONFIG_PATH') | default('/etc/kayobe', true) }}"

Expand Down
8 changes: 4 additions & 4 deletions ansible/inventory/group_vars/all/inspector
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ inspector_lldp_switch_port_interface_default: eth0
# check for an LLDP switch port description to use as the node's name.
inspector_lldp_switch_port_interface_map: {}

# Enable IPMI rules:
# Enable IPMI rules. Default is true.
inspector_rules_ipmi_enabled: True

# IPMI username referenced by inspector rule.
Expand All @@ -102,7 +102,7 @@ inspector_rule_var_ipmi_username:
# IPMI password referenced by inspector rule.
inspector_rule_var_ipmi_password:

# Enable Redfish rules
# Enable Redfish rules. Default is false.
inspector_rules_redfish_enabled: False

# Redfish username referenced by inspector rule.
Expand All @@ -111,10 +111,10 @@ inspector_rule_var_redfish_username:
# Redfish password referenced by inspector rule.
inspector_rule_var_redfish_password:

# Redfish CA setting.
# Redfish CA setting. Default is true.
inspector_rule_var_redfish_verify_ca: True

# Log Ironic inspector rules marked sensitive.
# Log Ironic inspector rules marked sensitive. Default is true.
ironic_inspector_sensitive_rule_no_log: True

# Ironic inspector rule to set IPMI credentials.
Expand Down
19 changes: 19 additions & 0 deletions ansible/lookup_plugins/kayobe_path.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Copyright (c) 2026 StackHPC Ltd.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.

__metaclass__ = type

import kayobe.plugins.lookup.kayobe_path

LookupModule = kayobe.plugins.lookup.kayobe_path.LookupModule
10 changes: 3 additions & 7 deletions ansible/roles/kolla-ansible/templates/overcloud-services.j2
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,11 @@ common
[fluentd:children]
common

[kolla-toolbox:children]
[kolla_logs:children]
common

[kolla_logs:children]
control
network
compute
storage
monitoring
[kolla_toolbox:children]
common

[opensearch:children]
control
Expand Down
8 changes: 4 additions & 4 deletions etc/kayobe/inspector.yml
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@
###############################################################################
# Ironic inspector introspection rules configuration.

# Ironic inspector option to enable IPMI rules. Set to 'True' by default.
# Ironic inspector option to enable IPMI rules. Default is true.
#inspector_rules_ipmi_enabled:

# Ironic inspector IPMI username to set.
Expand All @@ -86,7 +86,7 @@
# Ironic inspector uses IPMI by default enroll the baremetal nodes, however it
# is possible to use Redfish instead. To do that enable Redfish and make sure
# all of the necessary variables below have been properly set.
# Enable inspector Redfish rules. Set to 'False' by default.
# Enable inspector Redfish rules. Default is false.
#inspector_rules_redfish_enabled:

# Ironic inspector Redfish username to set.
Expand All @@ -95,10 +95,10 @@
# Ironic inspector Redfish password to set.
#inspector_redfish_password:

# Redfish CA setting. Set to 'True' by default
# Redfish CA setting. Default is true.
#inspector_rule_var_redfish_verify_ca:

# Log Ironic inspector rules marked sensitive. Set to 'True' by default
# Log Ironic inspector rules marked sensitive. Default is true.
#ironic_inspector_sensitive_rule_no_log:

# Ironic inspector rule to set IPMI credentials.
Expand Down
13 changes: 13 additions & 0 deletions kayobe/ansible.py
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,19 @@ def _get_environment(parsed_args, external_playbook=False):

env.setdefault("ANSIBLE_TEST_PLUGINS", ":".join(test_plugins))

if external_playbook:
lookup_plugins = [
os.path.join(parsed_args.config_path, "ansible", "lookup_plugins"),
utils.get_data_files_path("ansible", "lookup_plugins"),
]
else:
lookup_plugins = [
utils.get_data_files_path("ansible", "lookup_plugins"),
os.path.join(parsed_args.config_path, "ansible", "lookup_plugins"),
]

env.setdefault("ANSIBLE_LOOKUP_PLUGINS", ":".join(lookup_plugins))

return env


Expand Down
24 changes: 24 additions & 0 deletions kayobe/plugins/lookup/kayobe_path.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Copyright (c) 2026 StackHPC Ltd.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.

from ansible.plugins.lookup import LookupBase

from kayobe.utils import get_data_files_path

__version__ = "1.0.0"


class LookupModule(LookupBase):
def run(self, _terms, _variables=None, **_kwargs):
return [get_data_files_path("")]
26 changes: 26 additions & 0 deletions kayobe/tests/unit/test_ansible.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,10 @@ def test_run_playbooks(self, mock_validate, mock_vars, mock_run):
"/etc/kayobe/ansible/test_plugins",
utils.get_data_files_path("ansible", "test_plugins"),
]),
"ANSIBLE_LOOKUP_PLUGINS": ":".join([
"/etc/kayobe/ansible/lookup_plugins",
utils.get_data_files_path("ansible", "lookup_plugins"),
]),
}
mock_run.assert_called_once_with(expected_cmd, check_output=False,
quiet=False, env=expected_env)
Expand Down Expand Up @@ -132,6 +136,10 @@ def test_run_playbooks_internal(self, mock_validate, mock_vars, mock_run):
utils.get_data_files_path("ansible", "test_plugins"),
"/etc/kayobe/ansible/test_plugins",
]),
"ANSIBLE_LOOKUP_PLUGINS": ":".join([
utils.get_data_files_path("ansible", "lookup_plugins"),
"/etc/kayobe/ansible/lookup_plugins",
]),
}
mock_run.assert_called_once_with(expected_cmd, check_output=False,
quiet=False, env=expected_env)
Expand Down Expand Up @@ -251,6 +259,10 @@ def test_run_playbooks_all_the_args(self, mock_validate, mock_vars,
"/path/to/config/ansible/test_plugins",
utils.get_data_files_path("ansible", "test_plugins"),
]),
"ANSIBLE_LOOKUP_PLUGINS": ":".join([
"/path/to/config/ansible/lookup_plugins",
utils.get_data_files_path("ansible", "lookup_plugins"),
]),
}
mock_run.assert_called_once_with(expected_cmd, check_output=False,
quiet=False, env=expected_env)
Expand Down Expand Up @@ -314,6 +326,7 @@ def test_run_playbooks_all_the_long_args(self, mock_ask, mock_validate,
"ANSIBLE_ACTION_PLUGINS": mock.ANY,
"ANSIBLE_FILTER_PLUGINS": mock.ANY,
"ANSIBLE_TEST_PLUGINS": mock.ANY,
"ANSIBLE_LOOKUP_PLUGINS": mock.ANY,
}
expected_calls = [
mock.call(["which", "kayobe-vault-password-helper"],
Expand Down Expand Up @@ -356,6 +369,7 @@ def test_run_playbooks_vault_password_file(self, mock_update,
"ANSIBLE_ACTION_PLUGINS": mock.ANY,
"ANSIBLE_FILTER_PLUGINS": mock.ANY,
"ANSIBLE_TEST_PLUGINS": mock.ANY,
"ANSIBLE_LOOKUP_PLUGINS": mock.ANY,
}
mock_run.assert_called_once_with(expected_cmd, check_output=False,
quiet=False, env=expected_env)
Expand Down Expand Up @@ -395,6 +409,7 @@ def test_run_playbooks_vault_password_helper(self, mock_validate,
"ANSIBLE_ACTION_PLUGINS": mock.ANY,
"ANSIBLE_FILTER_PLUGINS": mock.ANY,
"ANSIBLE_TEST_PLUGINS": mock.ANY,
"ANSIBLE_LOOKUP_PLUGINS": mock.ANY,
}
mock_run.assert_called_once_with(expected_cmd, check_output=False,
quiet=False, env=expected_env)
Expand Down Expand Up @@ -462,6 +477,7 @@ def test_run_playbooks_func_args(self, mock_validate, mock_vars, mock_run):
"ANSIBLE_ACTION_PLUGINS": mock.ANY,
"ANSIBLE_FILTER_PLUGINS": mock.ANY,
"ANSIBLE_TEST_PLUGINS": mock.ANY,
"ANSIBLE_LOOKUP_PLUGINS": mock.ANY,
}
mock_run.assert_called_once_with(expected_cmd, check_output=False,
quiet=False, env=expected_env)
Expand Down Expand Up @@ -500,6 +516,7 @@ def test_run_playbooks_ignore_limit(self, mock_validate, mock_vars,
"ANSIBLE_ACTION_PLUGINS": mock.ANY,
"ANSIBLE_FILTER_PLUGINS": mock.ANY,
"ANSIBLE_TEST_PLUGINS": mock.ANY,
"ANSIBLE_LOOKUP_PLUGINS": mock.ANY,
}
mock_run.assert_called_once_with(expected_cmd, check_output=False,
quiet=False, env=expected_env)
Expand Down Expand Up @@ -538,6 +555,7 @@ def test_run_playbooks_list_tasks_arg(self, mock_validate, mock_vars,
"ANSIBLE_ACTION_PLUGINS": mock.ANY,
"ANSIBLE_FILTER_PLUGINS": mock.ANY,
"ANSIBLE_TEST_PLUGINS": mock.ANY,
"ANSIBLE_LOOKUP_PLUGINS": mock.ANY,
}
mock_run.assert_called_once_with(expected_cmd, check_output=False,
quiet=False, env=expected_env)
Expand Down Expand Up @@ -571,6 +589,7 @@ def test_run_playbooks_ansible_cfg(self, mock_validate, mock_vars,
"ANSIBLE_ACTION_PLUGINS": mock.ANY,
"ANSIBLE_FILTER_PLUGINS": mock.ANY,
"ANSIBLE_TEST_PLUGINS": mock.ANY,
"ANSIBLE_LOOKUP_PLUGINS": mock.ANY,
}
mock_run.assert_called_once_with(expected_cmd, check_output=False,
quiet=False, env=expected_env)
Expand Down Expand Up @@ -606,6 +625,7 @@ def test_run_playbooks_ansible_cfg_env(self, mock_validate, mock_vars,
"ANSIBLE_ACTION_PLUGINS": mock.ANY,
"ANSIBLE_FILTER_PLUGINS": mock.ANY,
"ANSIBLE_TEST_PLUGINS": mock.ANY,
"ANSIBLE_LOOKUP_PLUGINS": mock.ANY,
}
mock_run.assert_called_once_with(expected_cmd, check_output=False,
quiet=False, env=expected_env)
Expand Down Expand Up @@ -976,6 +996,7 @@ def test_multiple_inventory_args(self, mock_validate, mock_vars, mock_run):
"ANSIBLE_ACTION_PLUGINS": mock.ANY,
"ANSIBLE_FILTER_PLUGINS": mock.ANY,
"ANSIBLE_TEST_PLUGINS": mock.ANY,
"ANSIBLE_LOOKUP_PLUGINS": mock.ANY,
}
mock_run.assert_called_once_with(expected_cmd, check_output=False,
quiet=False, env=expected_env)
Expand Down Expand Up @@ -1021,6 +1042,7 @@ def exists_replacement(path):
"ANSIBLE_ACTION_PLUGINS": mock.ANY,
"ANSIBLE_FILTER_PLUGINS": mock.ANY,
"ANSIBLE_TEST_PLUGINS": mock.ANY,
"ANSIBLE_LOOKUP_PLUGINS": mock.ANY,
}
mock_run.assert_called_once_with(expected_cmd, check_output=False,
quiet=False, env=expected_env)
Expand Down Expand Up @@ -1064,6 +1086,7 @@ def exists_replacement(path):
"ANSIBLE_ACTION_PLUGINS": mock.ANY,
"ANSIBLE_FILTER_PLUGINS": mock.ANY,
"ANSIBLE_TEST_PLUGINS": mock.ANY,
"ANSIBLE_LOOKUP_PLUGINS": mock.ANY,
}
mock_run.assert_called_once_with(expected_cmd, check_output=False,
quiet=False, env=expected_env)
Expand Down Expand Up @@ -1108,6 +1131,7 @@ def exists_replacement(path):
"ANSIBLE_ACTION_PLUGINS": mock.ANY,
"ANSIBLE_FILTER_PLUGINS": mock.ANY,
"ANSIBLE_TEST_PLUGINS": mock.ANY,
"ANSIBLE_LOOKUP_PLUGINS": mock.ANY,
}
mock_run.assert_called_once_with(expected_cmd, check_output=False,
quiet=False, env=expected_env)
Expand Down Expand Up @@ -1157,6 +1181,7 @@ def exists_replacement(path):
"ANSIBLE_ACTION_PLUGINS": mock.ANY,
"ANSIBLE_FILTER_PLUGINS": mock.ANY,
"ANSIBLE_TEST_PLUGINS": mock.ANY,
"ANSIBLE_LOOKUP_PLUGINS": mock.ANY,
}
mock_run.assert_called_once_with(expected_cmd, check_output=False,
quiet=False, env=expected_env)
Expand Down Expand Up @@ -1238,6 +1263,7 @@ def exists_replacement(path):
"ANSIBLE_ACTION_PLUGINS": mock.ANY,
"ANSIBLE_FILTER_PLUGINS": mock.ANY,
"ANSIBLE_TEST_PLUGINS": mock.ANY,
"ANSIBLE_LOOKUP_PLUGINS": mock.ANY,
}
mock_run.assert_called_once_with(expected_cmd, check_output=False,
quiet=False, env=expected_env)
Expand Down
7 changes: 7 additions & 0 deletions releasenotes/notes/adds-kayobe-path-832afde0fd057569.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
features:
- |
Adds a new variable: ``kayobe_path``, which is set to the path of the git
repository where the Kayobe source code is located for editable installs,
or the installation path in the virtualenv where the ansible folder is
located, in the case of a regular install.
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
fixes:
- |
Fixes an issue where internal kayobe lookup plugins could not be used in
external playbooks.
`LP#2142876 <https://bugs.launchpad.net/kayobe/+bug/2142876>`__
Original file line number Diff line number Diff line change
Expand Up @@ -4,46 +4,37 @@ features:
Adds an opt-in ``nmstate`` network engine
(``network_engine: nmstate``) for host network configuration via
NetworkManager/libnmstate.
- |

Supports Ethernet, VLAN, bond, bridge, routes, and routing rules,
and adds OVS patch-link veth generation for overcloud bridge-to-OVS
connectivity.
- |

Adds structured ethtool configuration via
``<network>_ethtool_config`` for ring parameters and selected
offload features.
- |

The nmstate network engine is only supported on Rocky Linux. Ubuntu Noble
is not supported because the required system packages (nmstate,
python3-libnmstate) are not available in Ubuntu repositories. Attempting
to use nmstate on Ubuntu will fail with a clear error message directing
users to use the ``legacy`` network engine.
users to use the ``default`` network engine.

upgrade:
- |
Introduces ``network_engine`` in ``globals.yml``:
``legacy`` (default) and ``nmstate``.
Introduces ``network_engine`` in ``globals.yml`` to control which
engine is used to configure network interfaces. The options are ``default``,
which uses ``MichaelRigart.interfaces`` on Enterprise Linux and
systemd-networkd on Ubuntu, and ``nmstate``.
- |
With ``nmstate``, ethtool settings use structured YAML in
``<network>_ethtool_config``. ``legacy`` engine behavior is
``<network>_ethtool_config``. ``default`` engine behavior is
unchanged.
- |
With ``network_engine: nmstate``, ``<network>_rules`` entries must use
dict format (keys such as ``from``, ``to``, ``priority``, ``table``).
String-format rules are rejected on the ``nmstate`` path. ``legacy``
String-format rules are rejected on the ``nmstate`` path. ``default``
engine behavior is unchanged.
- |
Switching to ``nmstate`` may reconfigure host networking and cause
temporary connectivity disruption.

fixes:
- |
Fixes host configure regressions when using ``network_engine: nmstate`` on
Rocky Linux. Kayobe now ensures named route tables from
``network_route_tables`` are defined in ``/etc/iproute2/rt_tables`` for
nmstate-managed hosts. These fixes apply only to the ``nmstate`` engine
path; ``legacy`` engine behavior is unchanged.
- |
When using ``network_engine: nmstate`` with firewalld enabled, Kayobe now
reconciles interface-to-zone mappings in both permanent and runtime
firewalld configuration for interfaces that define ``<network>_zone``.
10 changes: 5 additions & 5 deletions requirements.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ collections:
type: git
version: master
- name: community.docker
version: 5.0.5
version: 5.1.0
- name: community.network
version: 5.1.0
- name: dellemc.os6
Expand All @@ -29,13 +29,13 @@ roles:
version: 1.3.2
- src: giovtorres.tuned
version: 2.0.2
- src: git+https://github.com/stackhpc/ansible-role-configdrive.git
name: jriguera.configdrive
version: fb199247333e72e38a9d414cf7b6144daa645477
- src: jriguera.configdrive
# There are no versioned releases of this role.
version: 17d9f7e76942012e9d09490ecb119066d16aad3d
- src: MichaelRigart.interfaces
version: v1.16.1
- src: mrlesmithjr.chrony
version: v0.1.6
version: v0.2.0
- src: mrlesmithjr.manage_lvm
version: v0.2.13
- src: mrlesmithjr.mdadm
Expand Down
Loading
Loading