End-to-end scenarios — neutron — branch stable/2026.2
Branch
stable/2026.2@eef1a0f7ee36— repository https://opendev.org/openstack/neutron — analysed on 2026-10-28
ML2/OVN reference profile. Participants: API = a neutron-server API worker (the one that receives the HTTP request, or the one the hash ring picks for an OVSDB event), MAINT = neutron-ovn-maintenance-worker, NB/SB = OVN databases, northd = ovn-northd, ctl = ovn-controller of a node, META = OVN metadata agent of that node. Statuses and messages are those of 02-errors_stable-2026.2.md; triggers are those of 05-async-processing_stable-2026.2.md.
1. Booting a VM on a project network
Nova creates (or receives) a port, binds it to the compute host, plugs the tap device and waits for network-vif-plugged before resuming the guest. Neutron's part: the logical switch port, the binding, the port status and the metadata namespace.
sequenceDiagram
autonumber
participant N as nova-compute
participant API as neutron API worker
participant DB as MariaDB
participant NB as OVN NB
participant SB as OVN SB
participant C as ovn-controller (compute)
participant M as OVN metadata agent (compute)
N->>API: POST /v2.0/ports {network_id, device_id, device_owner: compute:nova}
API->>DB: INSERT ports, ipallocations, standardattributes, ovn_revision_numbers
API->>NB: transact insert Logical_Switch_Port (addresses, port_security, port groups, DHCP options)
API->>DB: UPDATE ovn_revision_numbers (bump)
API-->>N: 201 {status: DOWN, binding:vif_type: unbound}
N->>API: PUT /v2.0/ports/{id} {binding:host_id: compute1}
API->>DB: INSERT provisioningblocks (L2), ml2_port_bindings
API->>API: bind_port: live OVN controller agent on compute1? physnet mapped?
alt chassis found
API->>DB: commit binding vif_type=ovs, vif_details {bridge_name: br-int, datapath_type}
API->>NB: transact update LSP options:requested-chassis=compute1
API-->>N: 200 {binding:vif_type: ovs}
else no chassis / dead agent
API-->>N: 200 {binding:vif_type: binding_failed}
Note over N: Nova fails the build ("Binding failed for port")
end
N->>C: plug tap (OVS Interface external_ids:iface-id = port id)
C->>SB: claim Port_Binding (chassis = compute1, up = true)
SB->>NB: northd copies up=true to Logical_Switch_Port.up
NB-->>API: update3 LSP up=true (LogicalSwitchPortUpdateUpEvent, hash ring)
API->>DB: provisioning complete → UPDATE ports SET status=ACTIVE
API->>N: POST /os-server-external-events network-vif-plugged (batched ≤ 2 s)
SB-->>M: update3 Port_Binding chassis set to us (PortBindingUpdatedEvent)
M->>M: create ovnmeta-<net> namespace, veth, 169.254.169.254, haproxySources: create (neutron/plugins/ml2/plugin.py:1675, neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/ovn_client.py:620-715), binding (neutron/plugins/ml2/plugin.py:651, neutron/plugins/ml2/drivers/ovn/mech_driver/mech_driver.py:1226-1405), status (neutron/plugins/ml2/drivers/ovn/mech_driver/mech_driver.py:1453-1507), Nova event (neutron/notifiers/nova.py:209-246), metadata (neutron/agent/ovn/metadata/agent.py:754-866).
Diagnostics:
binding:vif_type = binding_failed: look forRefusing to bind port … no OVN chassis for host/… dead agentin the server log; checkGET /v2.0/agents?host=compute1(OVN Controller agent alive?) and the chassisovn-bridge-mappingsfor flat/VLAN networks.- Port stays
DOWNand Nova times out waiting fornetwork-vif-plugged(default 300 s): checkovn-sbctl find Port_Binding logical_port=<id>(chassis,up); if OVN says up but Neutron says DOWN, the event was lost (hash ring empty, worker restart) — the maintenance task does not fix statuses, a port update or a restart of the API does [inferred]. - VM gets no metadata: check the
ovnmeta-<net>namespace on the node, the network's metadata port (device_owner=network:distributed) and the agent log (No port found in network …).
2. Router with an external gateway and a project subnet
sequenceDiagram
autonumber
actor U as Project user
participant API as neutron API worker
participant DB as MariaDB
participant NB as OVN NB
participant C as ovn-controller (gateway chassis)
U->>API: POST /v2.0/routers {external_gateway_info: {network_id: public}}
API->>DB: INSERT routers, gateway port (device_owner network:router_gateway), ovn_revision_numbers
API->>NB: lr_add neutron-<router>; LRP lrp-<gw port>; scheduler picks ≤5 gateway chassis → HA_Chassis_Group; static route 0.0.0.0/0 via public gateway IP
alt no candidate chassis
Note over API: WARNING Gateway … was not scheduled on any chassis (router has no external connectivity)
end
API-->>U: 201 {status: ACTIVE}
U->>API: PUT /v2.0/routers/{id}/add_router_interface {subnet_id}
API->>DB: INSERT ports (network:router_interface, gateway IP), routerports
API->>NB: LRP lrp-<port> (MAC, gateway CIDR); LSP type=router; NAT snat <subnet cidr> → <gateway IP>
API-->>U: 200 {port_id, subnet_id, …}
C->>C: highest-priority live chassis claims the chassisredirect port
C-->>API: SB Port_Binding chassis set (PortBindingChassisEvent)
API->>DB: UPDATE gateway port binding:host_id = gateway hostSources: neutron/db/l3_db.py:312, neutron/services/ovn_l3/service_providers/ovn.py:67-132, neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/ovn_client.py:1647-1677, 1465-1511, 1996-2056, scheduling 05 § 7.
Diagnostics: no external connectivity → ovn-nbctl lrp-get-gateway-chassis lrp-<gw port> / ha-chassis-group-list; empty means no chassis has enable-chassis-as-gw and the external physnet. 400 on add_router_interface: subnet without gateway IP, overlapping CIDR, subnet of another project (02 § 5).
3. Associating a floating IP (distributed)
sequenceDiagram
autonumber
actor U as Project user
participant API as neutron API worker
participant DB as MariaDB
participant NB as OVN NB
participant SB as OVN SB
U->>API: POST /v2.0/floatingips {floating_network_id, port_id}
API->>DB: INSERT port (network:floatingip), floatingips (router_id, fixed_ip), status DOWN
alt no router between the port's subnet and the floating network
API-->>U: 404 ExternalGatewayForFloatingIPNotFound
end
API->>NB: NAT dnat_and_snat (external_ip, logical_ip, logical_port, external_mac if LSP up)
API->>DB: UPDATE floatingips SET status=ACTIVE; bump revision
API-->>U: 201
NB-->>API: NAT created (FIPAddDeleteEvent)
API->>SB: ovsdb-client transact: delete MAC_Binding where ip = floating IP
Note over API,SB: when the VM port comes up later, set_port_status_up sets NAT external_macSources: neutron/db/l3_db.py:1510, neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/ovn_client.py:1010-1112, 1280-1301, neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/ovsdb_monitor.py:835-870, neutron/plugins/ml2/drivers/ovn/mech_driver/mech_driver.py:1416-1442.
Diagnostics: FIP ACTIVE but unreachable → check the NAT row (ovn-nbctl lr-nat-list neutron-<router>), whether external_mac is set (distributed mode needs the port up and a physnet on the compute node), and stale ARP entries upstream.
4. Adding a security group rule
sequenceDiagram
autonumber
actor U as Project user
participant API as neutron API worker
participant DB as MariaDB
participant NB as OVN NB
participant C as ovn-controller (all nodes with ports in the group)
U->>API: POST /v2.0/security-group-rules {security_group_id, direction, protocol, port_range…}
API->>DB: INSERT securitygrouprules (validation: duplicates → 409, invalid ranges → 400)
API->>NB: ACL on Port_Group pg_<sg> (priority 1002, allow-related, match "outport == @pg_… && ip4 && tcp && tcp.dst == 22")
API-->>U: 201
NB->>C: northd → logical flows → OpenFlow on every node hosting a member portSources: neutron/db/securitygroups_db.py:1014, neutron/plugins/ml2/drivers/ovn/mech_driver/mech_driver.py:537-566, neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/ovn_client.py:3078-3095.
Diagnostics: rule present in Neutron but not in OVN → ovn-nbctl acl-list pg_<sg>; the maintenance task re-creates missing ACLs within 5 minutes (check_for_inconsistencies).
5. Live migration of a VM
sequenceDiagram
autonumber
participant N as Nova (conductor/compute)
participant API as neutron API worker
participant NB as OVN NB
participant SB as OVN SB
participant D as ovn-controller (destination)
participant M as metadata agent (destination)
N->>API: POST /v2.0/ports/{id}/bindings {host: dest}
API-->>N: 201 binding INACTIVE (vif_details for dest)
N->>API: PUT /v2.0/ports/{id} {binding:profile: {migrating_to: dest}}
API->>NB: LSP options:requested-chassis = "src,dest"
SB-->>M: Port_Binding additional_chassis += dest (provision namespace early)
D->>SB: claim as additional chassis when the tap appears
N->>API: PUT /v2.0/ports/{id}/bindings/dest/activate
API->>NB: requested-chassis = dest
SB-->>API: Port_Binding chassis changed while up (PortBindingChassisUpdateEvent) → bump nb_cfg, wait for dest Chassis_Private.nb_cfg
API->>N: network-vif-plugged / network-changed eventsSources: neutron/plugins/ml2/plugin.py:2800, 2917, neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/ovn_client.py:552, neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/ovsdb_monitor.py:226-385, neutron/agent/ovn/metadata/agent.py:197-244.
Diagnostics: PortBindingAlreadyExists (409) when Nova retries a migration with a stale inactive binding: delete it with DELETE /ports/{id}/bindings/{host}; RevisionConflict retries during migration are logged at DEBUG and retried once (neutron/plugins/ml2/drivers/ovn/mech_driver/mech_driver.py:969-996).
6. OVN unavailable during an API call, then repair
sequenceDiagram
autonumber
actor U as User
participant API as neutron API worker
participant DB as MariaDB
participant NB as OVN NB
participant MAINT as maintenance worker
U->>API: PUT /v2.0/networks/{id} {name: new}
API->>DB: UPDATE networks, standardattributes.revision_number = 5 (commit)
API-xNB: transact update Logical_Switch (timeout 180 s / connection refused)
API-->>U: 500 (update stored, OVN not updated)
loop every 300 s, holding the OVSDB lock
MAINT->>DB: SELECT ovn_revision_numbers ⋈ standardattributes WHERE revisions differ AND older than 60 s
MAINT->>NB: update Logical_Switch with revision 5
MAINT->>DB: UPDATE ovn_revision_numbers SET revision_number = 5
endFor a create, the same failure makes ML2 delete the new object and return the error; for a delete, the API answers 204 and the maintenance task removes the OVN row later (02 § 4).
Sources: neutron/plugins/ml2/plugin.py:1366-1378, neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/maintenance.py:488-549, neutron/db/ovn_revision_numbers_db.py:224-263.
Diagnostics: neutron-ovn-db-sync-util --ovn-neutron_sync_mode=log lists the differences; the maintenance log shows Maintenance task: Failed to fix resource … for a resource that keeps failing.
Source: reverse-spec-neutron/04-scenarios_stable-2026.2.md. The _rewrite/ and _inventory/ files are not published on the site.