Add neutron.yml to baremetal env - #2527
Conversation
📝 WalkthroughAdds a baremetal Neutron configuration that sets WalkthroughThe bare-metal Neutron configuration now enables the ChangesNeutron configuration
Estimated code review effort: 1 (Trivial) | ~2 minutes Merge Risk: 🟡 Moderate · up to 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)
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. Comment |
There was a problem hiding this comment.
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
📒 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!
| kolla_neutron_ml2_mechanism_drivers: | ||
| - genericswitch | ||
| - ovn |
There was a problem hiding this comment.
🗄️ 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 || trueRepository: 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 || trueRepository: 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 || trueRepository: 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 || trueRepository: 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:
- 1: https://docs.openstack.org/networking-baremetal/latest/configuration/ml2/l2vni-mechanism-driver.html
- 2: https://docs.openstack.org/ironic/latest/admin/vxlan.html
- 3: https://docs.openstack.org/ironic/2026.1/admin/vxlan.html
- 4: https://docs.openstack.org/networking-baremetal/2026.1/configuration/ml2/l2vni-mechanism-driver.html
🌐 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 ismechanism_drivers = openvswitch,genericswitch. [1] - Networking Bare Metal uses the
baremetalmechanism driver, commonly alongside OVS:mechanism_drivers = openvswitch,baremetal. [2] - OVN uses
mechanism_drivers = ovn; its documentation does not indicate replacingovnwithgenericswitch. [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,genericswitchThis 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:
- 1: https://opendev.org/openstack/neutron/src/commit/5deea002aa4da506dc7c931c97cfc2414e66868b/doc/source/contributor/alembic_migrations.rst
- 2: https://opendev.org/openstack/neutron/src/commit/fce516e3461054716ff2d4623c240d3e006acbeb/setup.cfg
🏁 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
doneRepository: 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
doneRepository: 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")
PYRepository: 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")
PYRepository: 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")
PYRepository: 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")
PYRepository: 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.
|
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). |
Running
kayobe overcloud service deployto addbaremetalmixin would get error:Due to
kolla_neutron_ml2_mechanism_driversbeing undefined.This PR adds defaults for
kolla_neutron_ml2_mechanism_driversin thebaremetalenv.When added
service deployruns without error.