Skip to content

Add neutron.yml to baremetal env - #2527

Open
claudia-lola wants to merge 1 commit into
stackhpc/2026.1from
fix-baremetal-templating-error
Open

Add neutron.yml to baremetal env#2527
claudia-lola wants to merge 1 commit into
stackhpc/2026.1from
fix-baremetal-templating-error

Conversation

@claudia-lola

Copy link
Copy Markdown
Contributor

Running kayobe overcloud service deploy to add baremetal mixin would get error:

TASK [kolla-ansible : Ensure the Kolla global configuration file exists] ************************************************************************
Friday 21 August 2026  07:18:43 +0000 (0:00:00.582)       0:00:07.127 *********                                                                 
[ERROR]: Task failed: Error rendering template: argument of type 'NoneType' is not iterable                                                     
                                                                                                                                                 
Task failed.                                                                                                                                     
Origin: /home/cloud-user/deployment/venvs/kayobe/share/kayobe/ansible/roles/kolla-ansible/tasks/config.yml:50:3                                 
                                                                                                                                                 
48   when: (kayobe_environment | default('')) | length > 0                                                                                       
49                                                                                                                                               
50 - name: Ensure the Kolla global configuration file exists                                                                                     
     ^ column 3
                                                                                                                                                 
<<< caused by >>>                                                                                                                                
                                                                                                                                                 
Error rendering template: argument of type 'NoneType' is not iterable                                                                            
Origin: <unknown>                                                                                                                                
                                                                                                                                                 
# yamllint disable-file --- ############################################################################# # [...]
                                    
fatal: [localhost]: FAILED! =>                                                                                                                   
    changed: false                                                                                                                               
    msg: 'Task failed: Error rendering template: argument of type ''NoneType'' is not
        iterable'

PLAY RECAP **************************************************************************************************************************************
controller0                : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
localhost                  : ok=7    changed=0    unreachable=0    failed=1    skipped=3    rescued=0    ignored=0  

Due to kolla_neutron_ml2_mechanism_drivers being undefined.

This PR adds defaults for kolla_neutron_ml2_mechanism_drivers in the baremetal env.

When added service deploy runs without error.

@claudia-lola
claudia-lola requested a review from a team as a code owner August 21, 2026 10:23
@github-actions github-actions Bot added the waiting-review PR is waiting for a review label Aug 21, 2026
@coderabbitai

coderabbitai Bot commented Aug 21, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Adds a baremetal Neutron configuration that sets kolla_neutron_ml2_mechanism_drivers to genericswitch and ovn. This prevents kayobe overcloud service deploy from failing with a NoneType template-rendering error.

Walkthrough

The bare-metal Neutron configuration now enables the genericswitch and ovn ML2 mechanism drivers.

Changes

Neutron configuration

Layer / File(s) Summary
Configure ML2 mechanism drivers
etc/kayobe/environments/baremetal/neutron.yml
Adds genericswitch and ovn to the Neutron ML2 mechanism driver configuration.

Estimated code review effort: 1 (Trivial) | ~2 minutes

Merge Risk: 🟡 Moderate · up to 1b671

The new baremetal Neutron driver list places genericswitch before ovn, which can cause incorrect port-binding behavior. Reorder the drivers to place ovn before genericswitch before merging.

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Analyzed 0 functions across 0 files. (1 skipped: 1 unsupported.)
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1


ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 66b454bc-9749-4330-b9c6-60961f36da87

📥 Commits

Reviewing files that changed from the base of the PR and between e9abece and 1b6710a.

📒 Files selected for processing (1)
  • etc/kayobe/environments/baremetal/neutron.yml

Included review availability: Your plan provides up to 1 included review per hour; 0 remain after this review.

📜 Review details
⏰ Context from checks skipped due to timeout. (5)
  • GitHub Check: stackhpc/check
  • GitHub Check: Ansible 2.19 lint with Python 3.12
  • GitHub Check: Ansible 2.20 lint with Python 3.12
  • GitHub Check: Tox docs with Python 3.12
  • GitHub Check: Tox releasenotes with Python 3.12
🔇 Additional comments (1)
etc/kayobe/environments/baremetal/neutron.yml (1)

1-6: LGTM!

Comment on lines +7 to +9
kolla_neutron_ml2_mechanism_drivers:
- genericswitch
- ovn

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -eu
printf '%s\n' '--- target file ---'
cat -n etc/kayobe/environments/baremetal/neutron.yml
printf '%s\n' '--- references ---'
rg -n -C 3 'kolla_neutron_ml2_mechanism_drivers|genericswitch|ovn|ml2_conf' --glob '!*.lock' --glob '!*.min.*' .
printf '%s\n' '--- dependency/version files ---'
rg -n -C 2 'kolla-ansible|networking-baremetal|openstack.*release|branch|tag' \
  requirements*.txt setup.cfg pyproject.toml tox.ini .gitmodules .zuul.yaml .github 2>/dev/null || true

Repository: stackhpc/stackhpc-kayobe-config

Length of output: 50388


🏁 Script executed:

#!/bin/bash
set -eu
printf '%s\n' '--- target file ---'
cat -n etc/kayobe/environments/baremetal/neutron.yml
printf '%s\n' '--- references ---'
rg -n -C 3 'kolla_neutron_ml2_mechanism_drivers|genericswitch|ovn|ml2_conf' --glob '!*.lock' --glob '!*.min.*' .
printf '%s\n' '--- dependency/version files ---'
rg -n -C 2 'kolla-ansible|networking-baremetal|openstack.*release|branch|tag' \
  requirements*.txt setup.cfg pyproject.toml tox.ini .zuul.yaml .github 2>/dev/null || true

Repository: stackhpc/stackhpc-kayobe-config

Length of output: 50388


🏁 Script executed:

#!/bin/bash
set -eu
printf '%s\n' '--- target ---'
cat -n etc/kayobe/environments/baremetal/neutron.yml
printf '%s\n' '--- matching tracked text files ---'
git grep -n -I -E -e 'kolla_neutron_ml2_mechanism_drivers' -e 'genericswitch' -e 'ovn' -- \
  '*.yml' '*.yaml' '*.ini' '*.conf' '*.cfg' '*.md' '*.rst' '*.txt' '*.j2' '*.json' \
  ':!*.svg' ':!*.png' ':!*.jpg' | head -n 500
printf '%s\n' '--- repository metadata and dependency hints ---'
git ls-files | grep -E '(^|/)(requirements[^/]*|constraints[^/]*|setup\.cfg|pyproject\.toml|tox\.ini|\.gitmodules|README.*|.*version.*|.*release.*)$' | head -n 200
git grep -n -I -E -e 'kolla-ansible' -e 'networking-baremetal' -e 'kayobe' -- \
  'requirements*' 'constraints*' 'setup.cfg' 'pyproject.toml' 'tox.ini' '.gitmodules' \
  'README*' '*.md' '*.rst' 2>/dev/null | head -n 300 || true

Repository: stackhpc/stackhpc-kayobe-config

Length of output: 50387


🏁 Script executed:

#!/bin/bash
set -eu
for f in \
  etc/kayobe/environments/baremetal/kolla/config/neutron.conf \
  etc/kayobe/environments/baremetal/kolla/config/ironic-inspector.conf \
  etc/kayobe/environments/baremetal/kolla/config/nova.conf \
  etc/kayobe/environments/baremetal/kolla/globals.yml \
  etc/kayobe/neutron.yml \
  etc/kayobe/ansible/tools/check-kolla-ansible-version.yml \
  etc/kayobe/ansible/requirements.yml \
  etc/kayobe/environments/aio/release-train.yml \
  etc/kayobe/pulp-repo-versions.yml
do
  if [ -f "$f" ]; then
    printf '\n--- %s ---\n' "$f"
    cat -n "$f" | sed -n '1,180p'
  fi
done
printf '\n--- all kolla/neutron version references ---\n'
git grep -n -I -E 'kolla.*version|version.*kolla|kolla-ansible|networking-baremetal|generic.?switch' -- \
  'etc/kayobe/**/*.yml' 'etc/kayobe/**/*.yaml' 'etc/kayobe/**/*.j2' 'requirements*.txt' \
  'constraints*.txt' 2>/dev/null | head -n 500 || true

Repository: stackhpc/stackhpc-kayobe-config

Length of output: 22420


🌐 Web query:

OpenStack networking-baremetal genericswitch OVN mechanism_drivers order ovn genericswitch bare metal port binding

💡 Result:

In OpenStack environments integrating bare metal (Ironic) with OVN and Networking Generic Switch (genericswitch), the order of mechanism drivers in the /etc/neutron/plugins/ml2/ml2_conf.ini file is critical for successful port binding [1][2]. The recommended mechanism driver order is [1][2]: mechanism_drivers = ovn,baremetal_l2vni,baremetal,genericswitch Key drivers and their roles: 1. ovn: Must be listed first to provide the primary overlay network backend [1][3]. 2. baremetal_l2vni: Required for hierarchical port binding in VXLAN/Geneve deployments; it allocates VLANs and creates localnet ports to bridge the overlay network to the physical infrastructure [1][2]. 3. baremetal: Handles standard bare metal port binding [1][2]. 4. genericswitch: This or any other switch management plugin must be listed last [1][2]. It performs the final switch configuration step, such as mapping the allocated VLAN to the switch port [1][3]. Why the order matters: The genericswitch driver must be last because it relies on the VLAN information previously allocated by the baremetal_l2vni driver [1][4]. If the switch management plugin runs too early, it will lack the necessary configuration data, causing the port binding process to fail [1][3]. Proper hierarchical binding ensures that the physical switch is correctly programmed to support the logical overlay networks used by the bare metal nodes [2][3].

Citations:


🌐 Web query:

site:opendev.org/openstack/networking-baremetal genericswitch ovn mechanism_drivers

💡 Result:

Relevant OpenDev documentation:

  • Networking Generic Switch uses the ML2 mechanism driver name genericswitch; typical configuration is mechanism_drivers = openvswitch,genericswitch. [1]
  • Networking Bare Metal uses the baremetal mechanism driver, commonly alongside OVS: mechanism_drivers = openvswitch,baremetal. [2]
  • OVN uses mechanism_drivers = ovn; its documentation does not indicate replacing ovn with genericswitch. [3]
  • Generic Switch supports bare-metal ports with VNIC type baremetal, making it relevant for Ironic bare-metal networking. [4]

Thus, for an OVN-based deployment integrating Generic Switch, investigate whether your Neutron release supports combining them, but the documented driver names are:

[ml2]
mechanism_drivers = ovn,genericswitch

This combination may require release-specific compatibility validation.


🌐 Web query:

site:opendev.org/openstack/neutron ML2 mechanism drivers order bind_port hierarchical port binding

💡 Result:

In OpenStack Neutron's ML2 (Modular Layer 2) plugin, hierarchical port binding is a mechanism designed to support complex network topologies where a port may require multiple levels of binding to reach a destination host, such as in nested virtualization or environments with physical and virtual switch chaining [1]. Mechanism Drivers and Bind Port Process: 1. Mechanism Drivers (MDs): These drivers are responsible for taking actions on network resources. When a port binding request occurs, the ML2 plugin iterates through the configured mechanism drivers to determine which ones can successfully bind the port [2]. 2. Bind Port Flow: The process typically involves a driver attempting to bind a port for a given segment. If a driver cannot fully bind the port (e.g., it only handles a physical portion of the path), it can bind the port partially by specifying a subordinate segment. This triggers further binding attempts by other mechanism drivers for that segment, creating a hierarchy [1]. 3. Hierarchical Port Binding Levels: To track this process, Neutron uses the ml2_port_binding_levels database table [1]. This table records the binding sequence, storing the port_id, host, level (sequence of binding), driver, and segment_id [1]. 4. Execution: When a port is being bound, the ML2 plugin calls the bind_port method on mechanism drivers. A driver can either complete the binding by providing the necessary VIF (Virtual Interface) details or indicate that it requires a subordinate segment to be bound by another driver [1]. In essence, hierarchical port binding allows Neutron to decompose the binding process into sequential steps across different drivers, ensuring that complex network paths—such as those traversing both physical hardware switches and virtual overlays—are correctly configured [1].

Citations:


🏁 Script executed:

#!/bin/bash
set -eu
urls=(
  'https://docs.openstack.org/networking-baremetal/latest/configuration/ml2/l2vni-mechanism-driver.html'
  'https://docs.openstack.org/ironic/latest/admin/vxlan.html'
  'https://docs.openstack.org/networking-generic-switch/latest/'
  'https://opendev.org/openstack/networking-baremetal/raw/branch/master/networking_baremetal/ml2/mech_driver.py'
  'https://opendev.org/openstack/networking-generic-switch/raw/branch/master/networking_generic_switch/ml2/mech_driver.py'
  'https://opendev.org/openstack/neutron/raw/branch/master/neutron/plugins/ml2/managers.py'
)
for url in "${urls[@]}"; do
  printf '\n--- %s ---\n' "$url"
  curl -LfsS --max-time 20 "$url" |
    sed 's/<[^>]*>/ /g' |
    tr -s '[:space:]' ' ' |
    grep -ioE '.{0,180}(mechanism.drivers|genericswitch|baremetal_l2vni|hierarchical|bind_port|subsegment|ovn).{0,300}' |
    head -n 40 || true
done

Repository: stackhpc/stackhpc-kayobe-config

Length of output: 43339


🏁 Script executed:

#!/bin/bash
set -eu
printf '%s\n' '--- upstream repository trees ---'
for repo in networking-generic-switch networking-baremetal neutron; do
  url="https://opendev.org/api/contents/openstack/${repo}?ref=master"
  printf '\n%s\n' "$url"
  curl -LfsS --max-time 20 "$url" |
    python3 -c 'import json,sys; d=json.load(sys.stdin); print("\n".join(x.get("name","") for x in d if isinstance(x,dict)))' |
    head -n 100 || true
done

printf '%s\n' '--- candidate source files ---'
for path in \
  'networking-generic-switch/src/branch/master/networking_generic_switch/ml2/mech_driver.py' \
  'networking-generic-switch/src/branch/master/networking_generic_switch/ml2/mech_driver/__init__.py' \
  'networking-baremetal/src/branch/master/networking_baremetal/ml2/mech_driver.py' \
  'networking-baremetal/src/branch/master/networking_baremetal/ml2/mech_driver/__init__.py' \
  'neutron/src/branch/master/neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/mech_driver.py'
do
  url="https://opendev.org/openstack/${path}?format=raw"
  printf '\n--- %s ---\n' "$url"
  curl -LfsS --max-time 20 "$url" | grep -n -A35 -B10 -E 'def bind_port|continue_binding|set_binding|baremetal_l2vni|genericswitch' | head -n 160 || true
done

Repository: stackhpc/stackhpc-kayobe-config

Length of output: 3359


🏁 Script executed:

#!/bin/bash
set -eu
python3 - <<'PY'
import re
import subprocess
import urllib.request

target = "etc/kayobe/environments/baremetal/neutron.yml"
text = open(target, encoding="utf-8").read()
drivers = re.findall(r"^\s*-\s*([A-Za-z0-9_-]+)\s*$", text, re.MULTILINE)
print("target_drivers:", drivers)
assert drivers == ["genericswitch", "ovn"]

assignments = subprocess.check_output(
    ["git", "grep", "-n", "-I", "kolla_neutron_ml2_mechanism_drivers", "--",
     "*.yml", "*.yaml", "*.j2", "*.ini", "*.conf"],
    text=True,
    stderr=subprocess.DEVNULL,
)
print("tracked_assignments:")
print(assignments.strip())
assert assignments.count("kolla_neutron_ml2_mechanism_drivers:") == 2  # target plus commented generic default

source_url = (
    "https://opendev.org/openstack/neutron/raw/branch/master/"
    "neutron/plugins/ml2/managers.py"
)
source = urllib.request.urlopen(source_url, timeout=20).read().decode()
assert "self.ordered_mech_drivers.append(ext)" in source
assert "for driver in drivers:" in source
print("neutron_order_contract: configured extension order is appended and iterated")

doc_url = (
    "https://docs.openstack.org/networking-baremetal/latest/"
    "configuration/ml2/l2vni-mechanism-driver.html"
)
doc = urllib.request.urlopen(doc_url, timeout=20).read().decode(errors="replace")
plain = re.sub(r"<[^>]+>", " ", doc)
plain = re.sub(r"\s+", " ", plain)
assert "mechanism_drivers = ovn,baremetal_l2vni,baremetal,genericswitch" in plain
assert "Must be listed last" in plain
print("networking_baremetal_order_contract: genericswitch follows the lower-binding drivers")
PY

Repository: stackhpc/stackhpc-kayobe-config

Length of output: 304


🏁 Script executed:

#!/bin/bash
set -eu
python3 - <<'PY'
import re
import subprocess
import urllib.request

target = "etc/kayobe/environments/baremetal/neutron.yml"
text = open(target, encoding="utf-8").read()
drivers = re.findall(r"^\s*-\s*([A-Za-z0-9_-]+)\s*$", text, re.MULTILINE)
print("target_drivers:", drivers)
assert drivers == ["genericswitch", "ovn"]

assignments = subprocess.check_output(
    ["git", "grep", "-n", "-I", "kolla_neutron_ml2_mechanism_drivers", "--",
     "*.yml", "*.yaml", "*.j2", "*.ini", "*.conf"],
    text=True,
    stderr=subprocess.DEVNULL,
)
print("tracked_assignments:")
print(assignments.strip())
assert assignments.count("kolla_neutron_ml2_mechanism_drivers:") == 2

source_url = (
    "https://opendev.org/openstack/neutron/raw/branch/master/"
    "neutron/plugins/ml2/managers.py"
)
source = urllib.request.urlopen(source_url, timeout=20).read().decode()
assert "self.ordered_mech_drivers.append(ext)" in source
assert "for driver in drivers:" in source
print("neutron_order_contract: configured extension order is appended and iterated")

doc_url = (
    "https://docs.openstack.org/networking-baremetal/latest/"
    "configuration/ml2/l2vni-mechanism-driver.html"
)
doc = urllib.request.urlopen(doc_url, timeout=20).read().decode(errors="replace")
plain = re.sub(r"<[^>]+>", " ", doc)
plain = re.sub(r"\s+", " ", plain)
assert "mechanism_drivers = ovn,baremetal_l2vni,baremetal,genericswitch" in plain
assert "Must be listed last" in plain
print("networking_baremetal_order_contract: genericswitch follows the lower-binding drivers")
PY

Repository: stackhpc/stackhpc-kayobe-config

Length of output: 304


🏁 Script executed:

#!/bin/bash
set -eu
python3 - <<'PY'
import re
import subprocess
import urllib.request

target = "etc/kayobe/environments/baremetal/neutron.yml"
text = open(target, encoding="utf-8").read()
drivers = re.findall(r"^\s*-\s+([A-Za-z0-9_]+)\s*$", text, re.MULTILINE)
print("target_drivers:", drivers)
assert drivers == ["genericswitch", "ovn"]

assignments = subprocess.check_output(
    ["git", "grep", "-n", "-I", "kolla_neutron_ml2_mechanism_drivers", "--",
     "*.yml", "*.yaml", "*.j2", "*.ini", "*.conf"],
    text=True,
    stderr=subprocess.DEVNULL,
)
print("tracked_assignments:")
print(assignments.strip())
assert assignments.count("kolla_neutron_ml2_mechanism_drivers:") == 2

source_url = (
    "https://opendev.org/openstack/neutron/raw/branch/master/"
    "neutron/plugins/ml2/managers.py"
)
source = urllib.request.urlopen(source_url, timeout=20).read().decode()
assert "self.ordered_mech_drivers.append(ext)" in source
assert "for driver in drivers:" in source
print("neutron_order_contract: configured extension order is appended and iterated")

doc_url = (
    "https://docs.openstack.org/networking-baremetal/latest/"
    "configuration/ml2/l2vni-mechanism-driver.html"
)
doc = urllib.request.urlopen(doc_url, timeout=20).read().decode(errors="replace")
plain = re.sub(r"<[^>]+>", " ", doc)
plain = re.sub(r"\s+", " ", plain)
assert "mechanism_drivers = ovn,baremetal_l2vni,baremetal,genericswitch" in plain
assert "Must be listed last" in plain
print("networking_baremetal_order_contract: genericswitch follows the lower-binding drivers")
PY

Repository: stackhpc/stackhpc-kayobe-config

Length of output: 3489


🏁 Script executed:

#!/bin/bash
set -eu
python3 - <<'PY'
import re
import subprocess

target = "etc/kayobe/environments/baremetal/neutron.yml"
text = open(target, encoding="utf-8").read()
drivers = re.findall(r"^\s*-\s+([A-Za-z0-9_]+)\s*$", text, re.MULTILINE)
assert drivers == ["genericswitch", "ovn"]
print("target_drivers:", drivers)

assignments = subprocess.check_output(
    ["git", "grep", "-n", "-I", "kolla_neutron_ml2_mechanism_drivers", "--",
     "*.yml", "*.yaml", "*.j2", "*.ini", "*.conf"],
    text=True,
    stderr=subprocess.DEVNULL,
)
active = [
    line for line in assignments.splitlines()
    if re.search(r"kolla_neutron_ml2_mechanism_drivers:", line)
    and not re.search(r"#\s*kolla_neutron_ml2_mechanism_drivers:", line)
]
assert active == ["etc/kayobe/environments/baremetal/neutron.yml:7:kolla_neutron_ml2_mechanism_drivers:"]
print("active_assignments:", active)

def fetch(url):
    return subprocess.check_output(
        ["curl", "-LfsS", "--max-time", "20", url], text=True
    )

source = fetch(
    "https://opendev.org/openstack/neutron/raw/branch/master/"
    "neutron/plugins/ml2/managers.py"
)
assert "self.ordered_mech_drivers.append(ext)" in source
assert "for driver in drivers:" in source
print("neutron_order_contract: configured extension order is appended and iterated")

doc = fetch(
    "https://docs.openstack.org/networking-baremetal/latest/"
    "configuration/ml2/l2vni-mechanism-driver.html"
)
plain = re.sub(r"<[^>]+>", " ", doc)
plain = re.sub(r"\s+", " ", plain)
assert "mechanism_drivers = ovn,baremetal_l2vni,baremetal,genericswitch" in plain
assert "Must be listed last" in plain
print("networking_baremetal_order_contract: genericswitch follows lower-binding drivers")
PY

Repository: stackhpc/stackhpc-kayobe-config

Length of output: 476


Put ovn before genericswitch.

Neutron preserves this order during port binding. genericswitch must follow OVN and any enabled lower-binding drivers. Reorder the list to ovn, then genericswitch.

@mnasiadka

Copy link
Copy Markdown
Member

I think my main problem with all this, is that management of such overrides currently in Kayobe brings in a lot of complications (as in we don't merge these lists between each other - just the last one wins).
I don't know if that should be a stopper, but numerous people have been spending additional time analysing why some values of lists are not getting populated correctly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

waiting-review PR is waiting for a review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants