Add standalone networking service installation guide

Adds documentation covering the configuration and deployment of the
standalone networking service, which provides network switch management
for bare metal provisioning without requiring Neutron. The guide covers:

- Service architecture and components
- Configuration options
- Switch driver setup
- Network interface configuration
- Deployment and operation procedures

Related-Bug: 2113769
Assisted-by: Claude/sonnet-4.5
Change-Id: Iaa8d6ece141ff551abe7ffbef96be155b9b6b94a
Signed-off-by: Allain Legacy <alegacy@redhat.com>
This commit is contained in:
Allain Legacy
2026-02-05 07:38:18 -05:00
parent 4aa834e8d3
commit df13c4250d
6 changed files with 748 additions and 6 deletions
+25 -6
View File
@@ -83,7 +83,7 @@ Network interfaces
------------------
Network interface is one of the driver interfaces that manages network
switching for nodes. There are 3 network interfaces available in
switching for nodes. There are 4 network interfaces available in
the Ironic service:
- ``noop`` interface is used for standalone deployments, and does not perform
@@ -108,6 +108,18 @@ the Ironic service:
for IPv6 with Neutron also automatically creates multiple address records
for stateful address resolution.
- ``ironic-networking`` interface provides network switching for standalone
Ironic deployments without requiring the Networking service (Neutron). This
interface communicates directly with the ironic-networking service to
configure switch ports based on switchport configuration stored in each
port's ``extra`` field. Nodes move between provisioning, cleaning, rescuing,
inspection, and tenant networks during their life cycle. This interface is
suitable for environments where Ironic manages the network fabric directly.
This driver has different configuration requirements and doesn't follow
the VIF attachment flow or other related workflows described in this
document. Instead, see :doc:`/install/standalone/networking` for more
details.
To use these interfaces, they need to be enabled in *ironic.conf* utilizing
the :oslo.config:option:`enabled_network_interfaces` setting.
@@ -292,11 +304,18 @@ multiple network fabrics into the overall operation with Neutron.
Local link connection
---------------------
Use of the ``neutron`` network-interfaces_ requires the Ironic port
``local_link_connection`` information to be populated for each Ironic port
on a node in Ironic. This information is provided to the Neutron networking
service's ML2 driver when a Virtual Interface (VIF) is attached. The ML2
driver uses the information to plug the specified port to the tenant network.
Use of the ``neutron`` or ``ironic-networking`` network-interfaces_ requires
the Ironic port ``local_link_connection`` information to be populated for each
Ironic port on a node in Ironic.
In the context of the ``neutron`` network interface, this information is
provided to the networking service's ML2 driver when a Virtual Interface (VIF)
is attached. The ML2 driver uses the information to plug the specified port to
the tenant network.
In the context of the ``ironic-networking`` network interface, this information
is used by the Ironic Networking service to identify the switch port to be
configured.
This information is typically populated through the introspection process
by using LLDP data being broadcast from the switches, but may need to be
@@ -7,6 +7,12 @@ Below is an example flow of how to set up the Bare Metal service so that node
provisioning will happen in a multi-tenant environment (which means using the
``neutron`` network interface as stated above):
.. note::
For standalone deployments without the Networking service (Neutron), the
``ironic-networking`` network interface provides an alternative approach
for managing switch port configurations. See
:doc:`/install/standalone/networking` for details.
#. Network interfaces can be enabled on ironic-conductor by adding them to the
``enabled_network_interfaces`` configuration option under the ``default``
section of the configuration file::
+7
View File
@@ -47,6 +47,13 @@ ironic-novncproxy
A python service which proxies graphical consoles from hosts using the
NoVNC web browser interface.
ironic-networking
A python service which interacts with network switches to configure switch
ports when managing nodes. Nodes must be configured to use the
``ironic-networking`` network interface and must have appropriate attributes
set on the Ironic port.
See :doc:`standalone-networking </install/standalone/networking>`
Additionally, the Bare Metal service has certain external dependencies, which
are very similar to other OpenStack services:
+1
View File
@@ -10,6 +10,7 @@ the bare metal API directly, not though OpenStack Compute.
standalone/configure
standalone/enrollment
standalone/networking
Once the installation is done, please see :doc:`/user/deploy` for information
on how to deploy bare metal machines.
@@ -0,0 +1,696 @@
.. _configure-standalone-networking:
============================================
Configure the Standalone Networking Service
============================================
The Standalone Networking service provides network switch management for bare
metal provisioning in environments where Neutron is not available or not
desired. This service manages switch port configurations through a dedicated
``ironic-networking`` process that communicates with the Ironic conductor via
RPC. The service is capable of provisioning switch port attributes on the
neighboring switches to include VLAN configuration information for both access
and trunk ports.
.. Warning:: The standalone networking feature is experimental and the API may
change in future releases. Specifically, using the ``port.extra``
attribute to pass switchport configuration on each individual
port will be re-visited and likely converted to use a more formal
API structure.
.. Note:: The expected starting condition before a node is enrolled is that its
switch ports are configured onto the "idle" VLAN. The "idle" VLAN
can be considered as the default VLAN for a port. The networking
service will always set the switch port back to this VLAN whenever no
specific VLAN is required based on the state of the node. It is
expected that this VLAN is routable back to the Ironic API.
Nodes that are not configured onto the "idle" VLAN will fail the
initial inspection; therefore, no LLDP information will be available
to identify which switch ports need to be configured for that node.
In that case, ``local_link_connection`` information must be provided
manually for each port.
Overview
========
The standalone networking architecture consists of:
* **Networking Service** (``ironic-networking``): A standalone service that
manages network switch configurations via switch drivers
* **Switch Driver Framework**: Pluggable drivers for different network switch
vendors (e.g., generic-switch implemented using networking-generic-switch)
* **ironic-networking Network Interface**: An Ironic network interface
that integrates with the standalone networking service
* **RPC Communication**: Communication between conductor and networking service
using JSON-RPC or oslo-messaging supported backends like rabbitmq
Configuring Driver Interfaces
=============================
Switch Driver Framework
-----------------------
The switch driver framework within the ``ironic-networking`` service provides:
* **Driver Factory**: Dynamically loads switch drivers via stevedore
* **Base Driver Interface**: Common API for all switch drivers
* **Generic Switch Driver**: Built-in driver, named ``generic-switch``, using
networking-generic-switch
* **Driver Translators**: Convert generic switch configs to driver-specific
formats
ironic-networking Network Interface
-----------------------------------
The ``ironic-networking`` network interface (enabled per-node) provides:
* Integration between Ironic nodes and the networking service
* Switchport configuration validation via JSON schemas
* Support for ports, and planned support for portgroups (LAG)
* State-based network configuration (cleaning, provisioning, rescuing, etc.)
Installation and Dependencies
=============================
The standalone networking service requires the ``networking-generic-switch``
library for the generic-switch driver. Install it from the driver requirements
file::
$ pip install -r driver-requirements.txt
Configuration
=============
Authentication Strategies
-------------------------
The standalone networking service supports the following authentication
strategies for RPC communication between the Ironic conductor and the
networking service:
* ``keystone`` - Use OpenStack Identity service (Keystone) for authentication.
Recommended for production OpenStack deployments.
* ``http_basic`` - HTTP Basic authentication using an Apache-format htpasswd
file. Suitable for standalone deployments without Keystone.
* ``noauth`` - No authentication. **Not recommended for production** as it
provides no security.
The authentication strategy is configured via the ``auth_strategy`` option,
which can be set globally in ``[DEFAULT]`` or per-service in the
``[ironic_networking_json_rpc]`` section.
Creating the htpasswd File
^^^^^^^^^^^^^^^^^^^^^^^^^^
When using ``http_basic`` authentication, create the htpasswd file::
$ htpasswd -c -B /etc/ironic/htpasswd-rpc networking-rpc
Set appropriate permissions::
$ chmod 600 /etc/ironic/htpasswd-rpc
$ chown ironic:ironic /etc/ironic/htpasswd-rpc
RPC Transport Options
---------------------
Communication between the Ironic conductor and the networking service can use
one of two transport mechanisms:
* ``json-rpc`` - Direct JSON-RPC over HTTP/HTTPS. Simpler to configure for
standalone deployments.
* ``oslo_messaging`` - Oslo.messaging with a message broker (e.g., RabbitMQ).
Recommended for production OpenStack deployments as it provides better
reliability and is consistent with other OpenStack services.
Example: Production Configuration with Keystone and Oslo Messaging
------------------------------------------------------------------
This example shows a production-ready configuration using Keystone
authentication and RabbitMQ for RPC transport.
**Main Ironic Configuration (ironic.conf)**
.. code-block:: ini
[DEFAULT]
enabled_network_interfaces = ironic-networking,noop
auth_strategy = keystone
rpc_transport = oslo_messaging
transport_url = rabbit://ironic:password@rabbit-host:5672/
[ironic_networking]
rpc_transport = oslo_messaging
idle_network = access/native_vlan=123
inspection_network = access/native_vlan=123
[keystone_authtoken]
www_authenticate_uri = http://keystone-host:5000
auth_url = http://keystone-host:5000
auth_type = password
project_domain_name = Default
user_domain_name = Default
project_name = service
username = ironic
password = <ironic-service-password>
[oslo_messaging_rabbit]
rabbit_host = rabbit-host
rabbit_userid = ironic
rabbit_password = password
**Networking Service Configuration (ironic-networking.conf)**
.. code-block:: ini
[DEFAULT]
auth_strategy = keystone
rpc_transport = oslo_messaging
transport_url = rabbit://ironic:password@rabbit-host:5672/
[keystone_authtoken]
www_authenticate_uri = http://keystone-host:5000
auth_url = http://keystone-host:5000
auth_type = password
project_domain_name = Default
user_domain_name = Default
project_name = service
username = ironic-networking
password = <ironic-networking-service-password>
[oslo_messaging_rabbit]
rabbit_host = rabbit-host
rabbit_userid = ironic
rabbit_password = password
[ironic_networking]
enabled_switch_drivers = generic-switch
driver_config_dir = /var/lib/ironic/networking
switch_config_file = /etc/ironic/networking/switch-configs.conf
Example: Standalone Configuration with HTTP Basic Auth and JSON-RPC
-------------------------------------------------------------------
This example shows a simpler configuration suitable for standalone deployments
without Keystone or a message broker.
**Main Ironic Configuration (ironic.conf)**
.. code-block:: ini
[DEFAULT]
enabled_network_interfaces = ironic-networking,noop
auth_strategy = http_basic
http_basic_auth_user_file = /etc/ironic/htpasswd
[ironic_networking_json_rpc]
auth_strategy = http_basic
http_basic_auth_user_file = /etc/ironic/htpasswd-rpc
host_ip = localhost
port = 6190
username = networking-rpc
password = <rpc-password>
[ironic_networking]
rpc_transport = json-rpc
idle_network = access/native_vlan=123
inspection_network = access/native_vlan=123
**Networking Service Configuration (ironic-networking.conf)**
.. code-block:: ini
[DEFAULT]
auth_strategy = http_basic
http_basic_auth_user_file = /etc/ironic/htpasswd
rpc_transport = json-rpc
[ironic_networking_json_rpc]
auth_strategy = http_basic
http_basic_auth_user_file = /etc/ironic/htpasswd-rpc
host_ip = localhost
port = 6190
username = networking-rpc
password = <rpc-password>
[ssl]
cert_file = /etc/ironic/ssl/tls.crt
key_file = /etc/ironic/ssl/tls.key
[ironic_networking]
enabled_switch_drivers = generic-switch
driver_config_dir = /var/lib/ironic/networking
switch_config_file = /etc/ironic/networking/switch-configs.conf
Switch Configuration File (switch-configs.conf)
-----------------------------------------------
Create ``/etc/ironic/switch-configs.conf`` with your switch definitions.
This file uses a generic format that is translated to driver-specific
configuration by the driver adapter.
.. Note:: The networking service auto-generates driver-specific config files
in ``driver_config_dir`` from this generic configuration. You should
not manually create files in that directory.
Generic Format
^^^^^^^^^^^^^^
Each switch is defined in its own section with a name of your choice:
.. code-block:: ini
[switch-name]
# Switch connection information
address = 192.168.1.10
username = admin
password = secretpassword
# Driver type. Currently only "generic-switch"
driver_type = generic-switch
# Device type. Value specific to the driver type. (i.e., if driver type is
# generic-switch then device type should be one of the
# networking-generic-switch "generic_switch.devices" entry points.
# Example netmiko_dell_os10).
device_type = netmiko_cisco_ios
# Switch MAC address (for identification)
mac_address = 00:11:22:33:44:55
# Optional: SSH port (default: 22)
port = 22
# Optional: Enable secret for privileged mode
enable_secret = enablepassword
# Optional: SSH key file instead of password
# key_file = /path/to/ssh/key
# Optional: Save configuration after changes (default: false)
persist = false
# Optional: Filter which VLAN instance are allowed on the switch
allowed_vlans = 100,200-210
Example with multiple switches:
.. code-block:: ini
[tor-switch-1]
address = 192.168.1.10
username = admin
password = switch1pass
device_type = cisco_ios
enable_secret = enablepass
persist = true
mac_address = aa:bb:cc:dd:ee:01
[tor-switch-2]
address = 192.168.1.11
username = admin
password = switch2pass
device_type = arista_eos
mac_address = aa:bb:cc:dd:ee:02
Supported Device Types
^^^^^^^^^^^^^^^^^^^^^^
The generic-switch driver supports any device type supported by the
``networking-generic-switch`` library. Common types include:
* ``cisco_ios`` - Cisco IOS switches
* ``cisco_nxos`` - Cisco Nexus switches
* ``arista_eos`` - Arista EOS switches
* ``dell_os10`` - Dell OS10 switches
* ``juniper_junos`` - Juniper Junos switches
* ``ovs_linux`` - Open vSwitch (for testing)
See the networking-generic-switch documentation for the complete list of
supported device types.
Node Configuration
==================
Configuring Network Interface
-----------------------------
Set nodes to use the ``ironic-networking`` network interface:
.. code-block:: console
$ openstack baremetal node set <node> \
--network-interface ironic-networking
Override Default Networks (Optional)
------------------------------------
You can override the global network configuration per-node using ``driver_info``:
.. code-block:: console
$ openstack baremetal node set <node> \
--driver-info provisioning_network=access/native_vlan=250 \
--driver-info cleaning_network=access/native_vlan=150
Port Configuration with Switchport Information
----------------------------------------------
Each port must have ``local_link_connection`` and switchport configuration
in the ``extra`` field. The ``local_link_connection`` information is expected
to be populated automatically from LLDP at the end of inspection, or manually
if automatic inspection is not used or LLDP is not available.
The ``local_link_connection`` identifies the physical switch and port:
.. code-block:: json
{
"switch_id": "aa:bb:cc:dd:ee:01",
"port_id": "GigabitEthernet1/0/1",
"switch_info": "tor-switch-1"
}
The ``switch_id`` should match either the switch's MAC address or the name
used in ``switch-configs.conf``.
Switchport Configuration Schema
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The switchport configuration in ``port.extra.switchport`` must conform to this
schema:
**Required fields:**
* ``mode`` (string): Port mode - ``access``, ``trunk``, or ``hybrid``
* ``native_vlan`` (integer): Native VLAN ID (1-4094)
**Optional fields:**
* ``allowed_vlans`` (array of integers): Allowed VLAN IDs for trunk/hybrid
modes (required if mode is trunk or hybrid)
* ``mtu`` (integer): Maximum transmission unit (max: 9216)
**Validation rules:**
* Access mode: ``allowed_vlans`` must NOT be specified
* Trunk/Hybrid mode: ``allowed_vlans`` must be specified with at least one VLAN
* PXE-enabled ports: Must use ``access`` mode
Example: Access Mode Port
^^^^^^^^^^^^^^^^^^^^^^^^^
.. Note:: These examples manually set the local-link-connection info, but as
described earlier, these values could be received via LLDP during inspection
if both are enabled and available.
.. code-block:: console
$ openstack baremetal port create \
--node <node-uuid> \
--address aa:bb:cc:dd:ee:ff \
--local-link-connection switch_id=aa:bb:cc:dd:ee:01 \
--local-link-connection port_id=GigabitEthernet1/0/1 \
--local-link-connection switch_info=tor-switch-1 \
--extra switchport='{"mode": "access", "native_vlan": 100}' \
--pxe-enabled true
Example: Trunk Mode Port
^^^^^^^^^^^^^^^^^^^^^^^^
.. code-block:: console
$ openstack baremetal port create \
--node <node-uuid> \
--address aa:bb:cc:dd:ee:ff \
--local-link-connection switch_id=aa:bb:cc:dd:ee:01 \
--local-link-connection port_id=GigabitEthernet1/0/2 \
--local-link-connection switch_info=tor-switch-1 \
--extra switchport='{"mode": "trunk", "native_vlan": 1, "allowed_vlans": [100, 200, 300]}' \
--pxe-enabled false
Running the Networking Service
==============================
Standalone Mode
---------------
Run the networking service as a separate process:
.. code-block:: console
$ ironic-networking --config-file /etc/ironic/ironic.conf
Verify Service Status
---------------------
Check that the service initialized correctly by examining logs. You should
see log messages indicating:
* Number of driver-specific config files generated
* List of loaded switch drivers
* Networking service initialization on the configured host
Example output::
Networking service initialized with switch drivers: generic-switch
Generated 3 driver-specific config files during init
Troubleshooting
===============
Common Issues
-------------
**No switch drivers loaded**
If you see::
No switch drivers loaded - networking service will operate without switch
management capabilities
Check:
* ``enabled_switch_drivers`` is set in ``[ironic_networking]`` section
* Switch driver is installed (e.g., ``networking-generic-switch``)
* Driver entry point exists in ``ironic.networking.switch_drivers`` namespace
**Switch not found errors**
If switch operations fail with ``SwitchNotFound``:
* Verify ``switch_id`` in port's ``local_link_connection`` matches a switch
in ``switch-configs.conf``
* Check switch driver configuration was generated in ``driver_config_dir``
* Ensure switch MAC address or name matches exactly
**RPC communication failures**
For JSON-RPC connection issues:
* Verify ``host_ip`` and ``port`` in ``[ironic_networking_json_rpc]`` section
* Ensure networking service is running and listening
* Check firewall rules allow traffic on the configured port
For Oslo Messaging issues:
* Verify message bus (RabbitMQ) is running and accessible
* Check credentials in ``[oslo_messaging_rabbit]`` section
* Ensure conductor and networking service use the same transport URL
Debugging
---------
Enable debug logging in ``ironic.conf``:
.. code-block:: ini
[DEFAULT]
debug = true
log_file = /var/log/ironic/ironic-networking.log
This will show detailed information about:
* Switch driver loading and configuration
* RPC method calls and parameters
* Switch operations and responses
* VLAN validation results
Advanced Configuration
======================
VLAN Range Restrictions
-----------------------
The ``allowed_vlans`` configuration option restricts which VLAN IDs can be
used for port configuration. This setting can be configured globally in
``ironic.conf`` and optionally overridden on a per-switch basis in the
switch configuration file.
**Allow All VLANs (Default)**
If ``allowed_vlans`` is not specified or set to ``None``, all VLAN IDs
(1-4094) are permitted:
.. code-block:: ini
[ironic_networking]
# Not specified - all VLANs allowed (default behavior)
**Block All VLANs**
To prevent any VLAN configuration (useful for testing or maintenance):
.. code-block:: ini
[ironic_networking]
# Empty list - no VLANs allowed
allowed_vlans = []
**Allow Specific VLANs**
Restrict to specific VLAN IDs using individual values, ranges, or a
combination of both. Values are specified as a comma-separated list without
square brackets:
.. code-block:: ini
[ironic_networking]
# Allow individual VLANs (comma-separated)
allowed_vlans = 100,101,102,1000
# Allow VLAN ranges
allowed_vlans = 100-199,1000-1099
# Mixed individual and range notation
allowed_vlans = 100,101,102-104,106,200-299,1000
The last example allows VLANs: 100, 101, 102, 103, 104, 106, 200-299, and
1000, but denies 105 and all others outside the specified ranges.
**Per-Switch VLAN Restrictions**
Override global restrictions for specific switches in the switch
configuration file:
.. code-block:: ini
[tor-switch-1]
address = 192.168.1.10
username = admin
password = switchpass
device_type = cisco_ios
# Only specific VLANs on this switch
allowed_vlans = 200-299
[tor-switch-2]
address = 192.168.1.11
username = admin
password = switchpass
device_type = cisco_ios
# Only allow a different set of VLANs on this switch
allowed_vlans = 100-199,1000
**Validation Behavior**
When a port configuration operation is attempted:
1. The service checks if switch-specific ``allowed_vlans`` is configured
2. If not found, falls back to global ``[ironic_networking] allowed_vlans``
3. If neither is specified, all VLANs (1-4094) are allowed
4. If configured, any VLAN outside the allowed set will cause the operation
to fail.
The validation applies to both ``native_vlan`` and all VLANs in the
``allowed_vlans`` list for trunk/hybrid ports.
Network State Transitions
-------------------------
The ironic-networking interface manages switch configurations based on
node state and will configure the switch port to the corresponding network
configuration.
* **Inspection**: Configures ``inspection_network`` (if set)
* **Cleaning**: Configures ``cleaning_network`` (if set)
* **Provisioning**: Configures ``provisioning_network`` (if set)
* **Rescuing**: Configures ``rescuing_network`` (if set)
* **Servicing**: Configures ``servicing_network`` (if set)
* **Idle**: Reverts to ``idle_network`` (if set)
.. note::
The ``idle_network`` represents the default VLAN configuration that ports
should be set to when no specific network is required for the node's current
state. This network is used whenever a node transitions to a state that
doesn't have an explicit network configuration defined (e.g., ``available``,
``enroll``, ``manageable``). It's also used when exiting states like
cleaning, provisioning, or rescuing if no other network applies.
The idle network should be configured to allow connectivity back to the
Ironic API for inspection and management operations. If ``idle_network`` is
not configured, switch ports will not be configured (or will assume the
switch's own global default) when transitioning to idle states.
Security Considerations
=======================
Credential Management
---------------------
* Store switch passwords securely, not in plain text
* Use SSH keys (``key_file``) instead of passwords when possible
* Restrict file permissions on ``switch-configs.conf``::
$ chmod 600 /etc/ironic/switch-configs.conf
$ chown ironic:ironic /etc/ironic/switch-configs.conf
Switch Access Control
---------------------
* Use dedicated service accounts with minimal privileges for switch access
* Enable audit logging on switches for Ironic service account actions
* Regularly rotate switch credentials
Migration from Neutron
======================
If migrating from Neutron-based networking to standalone networking:
#. Ensure all nodes are in a stable state (``available`` or ``active``)
#. Update node configuration to use ``ironic-networking`` interface::
$ openstack baremetal node set <node> \
--network-interface ironic-networking
#. Add switchport configuration to ports (see Port Configuration section)
#. Configure and start the ``ironic-networking`` service
#. Test with a single node before migrating all nodes
.. note:: Ironic supports using different network interfaces on different nodes.
Therefore, it is possible to have some nodes migrated to the new
``ironic-networking`` network interface while others are still using
the ``neutron`` network interface.
Limitations and Future Work
===========================
Current Limitations
-------------------
* LAG operations are not yet implemented
* Limited to switches supported by networking-generic-switch
* No runtime reload of Ironic switch configuration file. Requires
ironic-networking service restart.
* Running multiple instances of ironic-networking for high-availability is not
supported.
References
==========
* :doc:`/admin/dhcp-less`
* :doc:`/admin/networking`
* :ref:`configure-networking`
* `networking-generic-switch documentation <https://networking-generic-switch.readthedocs.io/>`_
@@ -0,0 +1,13 @@
---
features:
- |
Adds a new standalone networking service that enables Ironic to manage
physical network switch configurations for bare metal nodes without
requiring Neutron. This service can run independently of the main Ironic
conductor, providing network switch management capabilities.
This feature is particularly useful for deployments where Neutron is not
available or where network switch management needs to be isolated from the
main conductor service for scalability or security reasons. The
ironic-networking interface is marked as experimental to allow for
feedback and iteration before becoming a stable interface.