Source code for ironic.common.trait_based_networking.plan

#    Licensed under the Apache License, Version 2.0 (the "License"); you may
#    not use this file except in compliance with the License. You may obtain
#    a copy of the License at
#
#         http://www.apache.org/licenses/LICENSE-2.0
#
#    Unless required by applicable law or agreed to in writing, software
#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
#    License for the specific language governing permissions and limitations
#    under the License.


from ironic.common.i18n import _
from ironic.common.trait_based_networking import base

from collections.abc import Callable
import itertools


[docs] def plan_network( network_trait: base.NetworkTrait, node_uuid: str, node_ports: list[base.Port], node_portgroups: list[base.Portgroup], node_networks: list[base.Network]) -> list[base.RenderedAction]: rendered_actions = [] # Order ports and portgroups by ID, newest first. node_ports.sort(key=lambda port: port.id, reverse=True) node_portgroups.sort(key=lambda portgroup: portgroup.id, reverse=True) portlikes = [base.Port.from_ironic_port(port) for port in node_ports] portgrouplikes = [base.Portgroup.from_ironic_portgroup(portgroup) for portgroup in node_portgroups] for trait_action in network_trait.actions: match trait_action.action: case base.Actions.ATTACH_PORT: rendered_actions.extend( plan_attach_portlike( trait_action, node_uuid, portlikes, node_networks, 'port', lambda action_args: base.AttachPort(*action_args))) case base.Actions.ATTACH_PORTGROUP: rendered_actions.extend( plan_attach_portlike( trait_action, node_uuid, portgrouplikes, node_networks, 'portgroup', lambda action_args: base.AttachPortgroup(*action_args))) # TODO(clif): Support bond_ports and group_and_attach_ports case _: rendered_actions.append( base.NotImplementedAction(trait_action.action)) return rendered_actions
[docs] def plan_attach_portlike( trait_action: base.NetworkTrait, node_uuid: str, node_portlikes: list[base.PrimordialPort], node_networks: list[base.Network], type_name: str, action_func: Callable[[base.NetworkTrait, str, str, str], base.RenderedAction] ) -> list[base.RenderedAction]: actions = [] for (portlike, network) in itertools.product(node_portlikes, node_networks): if trait_action.matches(portlike, network): actions.append(action_func((trait_action, node_uuid, portlike.uuid, network.id))) # No minimum count means match the first one. if trait_action.min_count is None: break if trait_action.max_count == len(actions): break if len(actions) == 0: return [base.NoMatch(trait_action, node_uuid, _(f"No ({type_name}, network) pairs matched " "rule."))] if (trait_action.min_count is not None and len(actions) < trait_action.min_count): return [base.NoMatch(trait_action, node_uuid, _(f"Not enough ({type_name}, network) pairs " "matched to meet minimum count threshold. " f"Matched {len(actions)} but min_count is " f"{trait_action.min_count}."))] return actions