Documentation for Trait Based Networking

Adds documentation for Ironic's new TBN feature.

Change-Id: I6c41ca0db52f69d819c683dd5804fa07846794d0
Signed-off-by: Clif Houck <me@clifhouck.com>
This commit is contained in:
Clif Houck
2026-02-04 12:21:40 -06:00
parent 128df02b30
commit cca4d18c91
8 changed files with 426 additions and 0 deletions

View File

@@ -29,3 +29,4 @@ Bare Metal Service Features
Node Health Monitoring <health-monitoring>
OCI Container Registry Support <oci-container-registry>
Runbooks for Cleaning & Servicing <runbooks>
Trait Based Networking (TBN) <trait-based-networking>

View File

@@ -126,6 +126,8 @@ the :oslo.config:option:`enabled_network_interfaces` setting.
VIF Attachment flow
-------------------
FIXME(clif): Probably need add a note and link to TBN related documentation here.
When creating a virtual interface (VIF), the action occurs against the
Neutron Networking Service, such as by using the ``openstack port create``
command, and then the port ID is submitted to Ironic to facilitate a VIF

View File

@@ -0,0 +1,90 @@
======================
Trait Based Networking
======================
Introduction
------------
Trait Based Networking, or TBN for short, is an Ironic feature that allows an
Openstack installation utilizing Ironic, Neutron, and Nova to dynamically
configure port scheduling for Ironic nodes.
Configure
---------
To configure and enable TBN for your Ironic installation please see
:doc:`/install/configure-trait-based-networking`
variable_name: /[a-z]+\.[a-z\_]+/
Available Actions
-----------------
Attach port - Attach one or more ports belonging to a node to a network
(aka vif)
Attach portgroup - Attach one or more portgroups belonging to a node to a
network (aka vif)
Future actions are coming.
Filter Expression Primer
------------------------
Filter Expressions are how network related objects are filtered or matched with
their applicable traits.
Let's look at a basic filter expression:
.. code-block:: console
port.vendor == "purple"
This expression consists of three parts:
#. A named variable: ``port.vendor`` - This means the expression will consider
a port's vendor field.
#. A comparator: ``==`` - In this case equality.
#. A string literal: ``"purple"`` - Gives a comparison value to compare against
the contents of the named variable.
Taken together this expression can be read in plain English as:
'filter for ports with vendor that is exactly equal to the string "purple"'.
All available variables and comparators are listed in the
:doc:`/references/trait-based-networking/filter-expression-reference`.
Single expressions can be linked together using boolean operators:
- "&&" boolean AND
- "||" boolean OR
Like so:
.. code-block:: console
port.vendor == "purple" && port.category != "privatenet"
Again in plain English this could be read as: 'filter for ports with vendor
that is exactly equal to the string "purple" and whose category field is not
"privatenet"'.
Functions
~~~~~~~~~
There's also a couple of functions available to filter ports vs portgroups:
- ``port.is_port`` will return true if the port is a port, and false otherwise.
- ``port.is_portgroup`` will return true if the port is a portgroup, and false
otherwise.
Function expressions can be used in isolation:
.. code-block:: console
port.is_port
Or linked with other expressions:
.. code-block:: console
port.is_port && port.vendor == "green"

View File

@@ -9,6 +9,7 @@ Integration with other OpenStack services
configure-compute
configure-networking
configure-ipv6-networking
configure-trait-based-networking
configure-glance-swift
enabling-https
configure-cleaning

View File

@@ -0,0 +1,42 @@
.. _configure-trait-based-networking:
Configure Trait Based Networking to Plan Networking Related Operations at vif Attach
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Ironic has a feature called Trait Based Networking (or TBN) that allows
operators to configure how a node's network will be built and attached.
TBN applies to OpenStack installations utilizing Ironic, Neutron, and Nova
that want dynamic port scheduling based on networks and flavors chosen by the
instance creator.
In order to use this feature, a few steps must be completed.
#. Enable Trait Based Networking in the ironic-conductor service configuration:
.. code-block:: ini
[conductor]
# Enables Trait Based Networking, defaults to False
enable_trait_based_networking=True
#. Place a TBN configuration file in the configured location. The default
location is: ``/etc/ironic/trait_based_networking.yaml``.
For discussion of the syntax and format of the configuration file refer to
:doc:`/references/trait-based-networking/tbn-config-file`.
The default configuration which ships with Ironic is reproduced below:
.. include:: ../../../etc/ironic/trait_based_networks.yaml.sample
:code: yaml
#. Set desired TBN traits on a node's ``instance_info.traits``. Trait names
must match exactly for a TBN trait to be applied.
Then, when ``vif_attach`` is called, TBN will plan networking operations based
on the node's ``instance_info.traits`` and supplied configured traits. If
planning succeeds, then each network operation will be applied.

View File

@@ -21,3 +21,12 @@ CLI References
- `Ironic CLI <https://docs.openstack.org/python-ironicclient/latest/cli/>`_
- :doc:`ironic-dbsync </cli/ironic-dbsync>`
- `ironic-status <https://docs.openstack.org/ironic/latest/cli/ironic-status.html>`_
Trait Based Networking Reference
--------------------------------
.. toctree::
:maxdepth: 1
TBN Configuration File <trait-based-networking/tbn-config-file>
Filter Expression Reference <trait-based-networking/filter-expression-reference>

View File

@@ -0,0 +1,208 @@
Filter Expression Reference
===========================
This reference is for Trait Based Networking's Filter Expressions.
.. note::
If this document disagrees with
``ironic.common.trait_based_networking.grammar.parser.FILTER_EXPRESSION_GRAMMAR``
then this document is wrong. `FILTER_EXPRESSION_GRAMMAR`_ is the ultimate
source of truth regarding the grammar and parsing of TBN filter expressions.
Filter Expressions
------------------
A filter expression is a boolean expression which evaluates to ``True`` if the
objects under consideration match the filter, and ``False`` otherwise.
Filter expressions allow Ironic operators to create custom filtering logic for
traits which will apply specific network actions or operations to nodes.
Filter expressions consider two basic network objects:
1. ``portlike``: (aka ``port`` in this document) which can be either an Ironic
port or portgroup.
2. ``network``: Essentially a Neutron vif (virtual interface).
A filter expression that evaluates to ``True`` for a given tuple of
``(portlike, network)`` would cause a match to occur for the trait the filter
belongs to. The trait's defined actions would then apply if enough matches
occur to satisfy the action's requirements.
Single Expression
^^^^^^^^^^^^^^^^^
A ``single expression`` has the form of:
.. code-block:: python
variable_name comparator string_literal
Where ``variable_name`` is one of the available `variables`_, ``comparator``
is one of the available `comparators`_, and ``string_literal`` is a valid
`string literal`_.
A full example of a single expression:
.. code-block:: python
port.category == 'public'
Which would evaluate to ``True`` whenever a portlike is considered that has a
``category`` that exactly equals ``public``.
Function Expression
^^^^^^^^^^^^^^^^^^^
A ``function expression`` has the form of:
.. code-block:: python
function
See `Functions`_ for available ``functions``.
Compound Expression
^^^^^^^^^^^^^^^^^^^
A compound expression consists of two expressions joined by a
`comparator`_.
.. code-block:: python
port.category == 'public' && port.vendor == 'green'
Parenthesis
^^^^^^^^^^^
Parenthesis can be used to group expressions together to guarantee evaluation
precedence. For example:
.. code-block:: python
port.category == 'private' || (port.vendor == 'purple' && network.name == 'hypernet')
Would cause the right-hand side of ``||`` to be evaluated together before
evaluating the result against the left side of ``||``.
.. _comparator:
Comparators
-----------
Comparators allow comparisons between variables and string literals.
========== ======================= ==========================================
Comparator Name Explanation
========== ======================= ==========================================
``==`` Equality Check for exact matches.
``!=`` Inequality Check for any difference.
``>=`` Greater than or equal Is the variable greater than or equal to the string literal?
``>`` Greater than Is the variable greater than the string literal?
``<=`` Less than or equal Is the variable less than or equal to the string literal?
``<`` Less than Is the variable less than the string literal?
``=~`` Prefix match Does the beginning of the variable match the string literal?
========== ======================= ==========================================
Examples
^^^^^^^^
.. code-block:: python
port.vendor == 'purple'
If a port's ``vendor`` is exactly ``purple`` then this expression will
evaluate to ``True`` and ``False`` otherwise.
.. code-block:: python
port.category =~ 'green'
If a port's ``category`` starts with the string ``green`` then this expression
will evaluate to ``True`` and ``False`` otherwise.
.. code-block:: python
network.name != 'private'
Match only networks if their name name is NOT ``private``.
.. _boolean-operator:
Boolean Operators
-----------------
Used to join expressions to create complex filtering logic.
======== ==== ======================================================
Operator Name Explanation
======== ==== ======================================================
``&&`` And If both expressions are ``True``, then return ``True``.
``||`` Or If either expression is ``True``, then return ``True``.
======== ==== ======================================================
Examples
^^^^^^^^
.. code-block:: python
port.vendor == 'purple' && port.category == 'private'
Will match a port if it's ``vendor`` is ``purple`` and it's category is
``private``.
.. code-block:: python
port.vendor == 'purple' || port.vendor == 'green'
Will match a port if it's ``vendor`` is ``purple`` or ``green``.
Functions
---------
Functions allow basic querying of TBN related objects.
================= ===================================================================
Function Explanation
================= ===================================================================
port.is_port Returns ``True`` if the portlike under consideration is a ``port``.
port.is_portgroup Returns ``True`` if the portlike under consideration is a ``portgroup``.
================= ===================================================================
Examples
^^^^^^^^
.. code-block:: python
port.is_port
Will match portlikes which are a ``port``.
String literal
--------------
String literals are enclosed by single quotes: ``'``.
String literals only allow alphanumeric characters, underscores, dashes, and
periods.
The following regular expression encompasses valid string literals:
``/\'[A-Za-z0-9_\-\.]*\'/``
Variables
---------
Variables allow basic querying of network related objects in filter
expressions. Available variables are listed below:
- network.name
- network.tags
- port.address
- port.category
- port.physical_network
- port.vendor
.. _FILTER_EXPRESSION_GRAMMAR: https://opendev.org/openstack/ironic/src/branch/master/ironic/common/trait_based_networking/grammar/parser.py#L17

View File

@@ -0,0 +1,73 @@
===================================================
Trait Based Networking Configuration File Reference
===================================================
Introduction
------------
Trait Based Networking's trait configuration file is a YAML format file which
defines a set of traits, and their corresponding actions. This file is
ingested and validated by the Ironic conductor at start-up.
Trait Layout
------------
Below is a valid YAML example trait:
.. code-block:: yaml
CUSTOM_TRAIT_NAME:
order: 1
actions:
- action: bond_ports
filter: port.vendor == 'vendor_string'
min_count: 2
- action: attach_port
filter: port.vendor == 'vendor_string' && port.is_portgroup
max_count: 1
``CUSTOM_TRAIT_NAME`` is the trait's name. Each trait is identified by a name
which *must* start with ``CUSTOM``. It's ``order`` is ``1``. Ordering is
ascending, so lower orders will apply first.
``actions`` is a list of actions to apply if this trait matches one defined
in a node's ``instance_info.traits`` field.
Each action has the following necessary keys:
* ``action`` - The action to take.
* ``filter`` - The Filter Expression to apply with this action.
.. note::
Refer to
:doc:`/references/trait-based-networking/filter-expression-reference` for
detailed explanations on how to write valid filter expressions.
and the following optional keys:
* ``max_count`` - The maximum number of objects that can match this action.
There is no default maximum.
* ``min_count`` - The minimum number of objects that *must* match before this
action applies. The default minimum is effectively 1.
Available Actions
-----------------
The following actions are currently available:
* ``attach_port`` - Attach (port, network) pairs that pass this action's
filter expression.
* ``attach_portgroup`` - Attach (portgroup, network) pairs that pass this
action's filter expression.
Future actions are planned. This document will be updated as they become
available.
Example Configuration File
--------------------------
An example Trait Based Networking configuration file is shipped with Ironic.
A copy is `available here <https://opendev.org/openstack/ironic/src/branch/master/etc/ironic/trait_based_networks.yaml.sample>`_.
While backwards compatibility breaking changes are generally avoided where
possible, please be aware that the linked copy may not be compatible with your
version of Ironic.