Skip to content

Commit 50c6bbf

Browse files
authored
Merge pull request #113 from stackhpc/upstream/master-2025-04-21
Synchronise master with upstream
2 parents aeba241 + 18db751 commit 50c6bbf

29 files changed

+1942
-243
lines changed

devstack/plugin.sh

Lines changed: 55 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -124,45 +124,46 @@ function configure_generic_switch {
124124
# Generate SSH keypair
125125
configure_generic_switch_user
126126

127-
sudo ovs-vsctl --may-exist add-br $GENERIC_SWITCH_TEST_BRIDGE
128-
ip link show gs_port_01 || sudo ip link add gs_port_01 type dummy
129-
sudo ovs-vsctl --may-exist add-port $GENERIC_SWITCH_TEST_BRIDGE $GENERIC_SWITCH_TEST_PORT
130-
if [[ "$GENERIC_SWITCH_USER_MAX_SESSIONS" -gt 0 ]]; then
131-
# NOTE(pas-ha) these are used for concurrent tests in tempest plugin
132-
N_PORTS=$(($GENERIC_SWITCH_USER_MAX_SESSIONS * 2))
133-
for ((n=0;n<$N_PORTS;n++)); do
134-
sudo ovs-vsctl --may-exist add-port $GENERIC_SWITCH_TEST_BRIDGE ${GENERIC_SWITCH_TEST_PORT}_${n}
135-
done
136-
fi
127+
if [[ "${IRONIC_NETWORK_SIMULATOR:-ovs}" == "ovs" ]]; then
128+
sudo ovs-vsctl --may-exist add-br $GENERIC_SWITCH_TEST_BRIDGE
129+
ip link show gs_port_01 || sudo ip link add gs_port_01 type dummy
130+
sudo ovs-vsctl --may-exist add-port $GENERIC_SWITCH_TEST_BRIDGE $GENERIC_SWITCH_TEST_PORT
131+
if [[ "$GENERIC_SWITCH_USER_MAX_SESSIONS" -gt 0 ]]; then
132+
# NOTE(pas-ha) these are used for concurrent tests in tempest plugin
133+
N_PORTS=$(($GENERIC_SWITCH_USER_MAX_SESSIONS * 2))
134+
for ((n=0;n<$N_PORTS;n++)); do
135+
sudo ovs-vsctl --may-exist add-port $GENERIC_SWITCH_TEST_BRIDGE ${GENERIC_SWITCH_TEST_PORT}_${n}
136+
done
137+
fi
137138

138-
if [ -e "$HOME/.ssh/id_rsa" ] && [[ "$HOST_TOPOLOGY" == "multinode" ]]; then
139-
# NOTE(TheJulia): Reset the key pair to utilize a pre-existing key,
140-
# this is instead of generating one, which doesn't work in multinode
141-
# environments. This is because the keys are managed and placed by zuul.
142-
GENERIC_SWITCH_KEY_FILE="${HOME}/.ssh/id_rsa"
143-
fi
139+
if [ -e "$HOME/.ssh/id_rsa" ] && [[ "$HOST_TOPOLOGY" == "multinode" ]]; then
140+
# NOTE(TheJulia): Reset the key pair to utilize a pre-existing key,
141+
# this is instead of generating one, which doesn't work in multinode
142+
# environments. This is because the keys are managed and placed by zuul.
143+
GENERIC_SWITCH_KEY_FILE="${HOME}/.ssh/id_rsa"
144+
fi
144145

145-
# Create generic_switch ml2 config
146-
for switch in $GENERIC_SWITCH_TEST_BRIDGE $IRONIC_VM_NETWORK_BRIDGE; do
147-
local bridge_mac
148-
bridge_mac=$(ip link show dev $switch | egrep -o "ether [A-Za-z0-9:]+"|sed "s/ether\ //")
149-
switch="genericswitch:$switch"
150-
add_generic_switch_to_ml2_config $switch $GENERIC_SWITCH_KEY_FILE $GENERIC_SWITCH_USER ::1 netmiko_ovs_linux "$GENERIC_SWITCH_PORT" "$bridge_mac"
151-
done
152-
echo "HOST_TOPOLOGY: $HOST_TOPOLOGY"
153-
echo "HOST_TOPOLOGY_SUBNODES: $HOST_TOPOLOGY_SUBNODES"
154-
if [ -n "$HOST_TOPOLOGY_SUBNODES" ]; then
155-
# NOTE(vsaienko) with multinode topology we need to add switches from all
156-
# the subnodes to the config on primary node
157-
local cnt=0
158-
local section
159-
for node in $HOST_TOPOLOGY_SUBNODES; do
160-
cnt=$((cnt+1))
161-
section="genericswitch:sub${cnt}${IRONIC_VM_NETWORK_BRIDGE}"
162-
add_generic_switch_to_ml2_config $section $GENERIC_SWITCH_KEY_FILE $GENERIC_SWITCH_USER $node netmiko_ovs_linux "$GENERIC_SWITCH_PORT"
146+
# Create generic_switch ml2 config
147+
for switch in $GENERIC_SWITCH_TEST_BRIDGE $IRONIC_VM_NETWORK_BRIDGE; do
148+
local bridge_mac
149+
bridge_mac=$(ip link show dev $switch | egrep -o "ether [A-Za-z0-9:]+"|sed "s/ether\ //")
150+
switch="genericswitch:$switch"
151+
add_generic_switch_to_ml2_config $switch $GENERIC_SWITCH_KEY_FILE $GENERIC_SWITCH_USER ::1 netmiko_ovs_linux "$GENERIC_SWITCH_PORT" "$bridge_mac"
163152
done
153+
echo "HOST_TOPOLOGY: $HOST_TOPOLOGY"
154+
echo "HOST_TOPOLOGY_SUBNODES: $HOST_TOPOLOGY_SUBNODES"
155+
if [ -n "$HOST_TOPOLOGY_SUBNODES" ]; then
156+
# NOTE(vsaienko) with multinode topology we need to add switches from all
157+
# the subnodes to the config on primary node
158+
local cnt=0
159+
local section
160+
for node in $HOST_TOPOLOGY_SUBNODES; do
161+
cnt=$((cnt+1))
162+
section="genericswitch:sub${cnt}${IRONIC_VM_NETWORK_BRIDGE}"
163+
add_generic_switch_to_ml2_config $section $GENERIC_SWITCH_KEY_FILE $GENERIC_SWITCH_USER $node netmiko_ovs_linux "$GENERIC_SWITCH_PORT"
164+
done
165+
fi
164166
fi
165-
166167
neutron_server_config_add $GENERIC_SWITCH_INI_FILE
167168

168169
}
@@ -175,11 +176,22 @@ function add_generic_switch_to_ml2_config {
175176
local device_type=$5
176177
local port=$6
177178
local ngs_mac_address=$7
178-
179-
populate_ml2_config $GENERIC_SWITCH_INI_FILE $switch_name key_file=$key_file
179+
local password=$8
180+
local enable_secret=$9
181+
# Use curly braces above 9 to prevent expression expansion
182+
local trunk_interface="${10}"
183+
184+
if [[ -n "$key_file" ]]; then
185+
populate_ml2_config $GENERIC_SWITCH_INI_FILE $switch_name key_file=$key_file
186+
elif [[ -n "$password" ]]; then
187+
populate_ml2_config $GENERIC_SWITCH_INI_FILE $switch_name password=$password
188+
fi
180189
populate_ml2_config $GENERIC_SWITCH_INI_FILE $switch_name username=$username
181190
populate_ml2_config $GENERIC_SWITCH_INI_FILE $switch_name ip=$ip
182191
populate_ml2_config $GENERIC_SWITCH_INI_FILE $switch_name device_type=$device_type
192+
if [[ -n "$enable_secret" ]]; then
193+
populate_ml2_config $GENERIC_SWITCH_INI_FILE $switch_name secret=$enable_secret
194+
fi
183195
if [[ -n "$port" ]]; then
184196
populate_ml2_config $GENERIC_SWITCH_INI_FILE $switch_name port=$port
185197
fi
@@ -190,6 +202,9 @@ function add_generic_switch_to_ml2_config {
190202
if [[ "$device_type" =~ "netmiko" && "$GENERIC_SWITCH_USER_MAX_SESSIONS" -gt 0 ]]; then
191203
populate_ml2_config $GENERIC_SWITCH_INI_FILE $switch_name ngs_max_connections=$GENERIC_SWITCH_USER_MAX_SESSIONS
192204
fi
205+
if [[ -n "$trunk_interface" ]]; then
206+
populate_ml2_config $GENERIC_SWITCH_INI_FILE $switch_name ngs_trunk_ports=$trunk_interface
207+
fi
193208
}
194209

195210
function cleanup_networking_generic_switch {
@@ -220,6 +235,9 @@ function ngs_configure_tempest {
220235
if [ $GENERIC_SWITCH_USER_MAX_SESSIONS -gt 0 ]; then
221236
iniset $TEMPEST_CONFIG ngs port_dlm_concurrency $(($GENERIC_SWITCH_USER_MAX_SESSIONS * 2))
222237
fi
238+
if [[ "${ML2_L3_PLUGIN:-}" =~ "trunk" ]]; then
239+
iniset $TEMPEST_CONFIG baremetal_feature_enabled trunks_supported True
240+
fi
223241
}
224242

225243
# check for service enabled

doc/source/supported-devices.rst

Lines changed: 82 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ The following devices are supported by this plugin:
1212
* Cisco NX-OS switches (Nexus)
1313
* Cumulus Linux (via NCLU)
1414
* Cumulus Linux (via NVUE)
15-
* Dell Force10
16-
* Dell OS10
15+
* Dell Force10 (netmiko_dell_force10)
16+
* Dell OS10 (netmiko_dell_os10)
1717
* Dell PowerConnect
1818
* HPE 5900 Series switches
1919
* Huawei switches
@@ -32,4 +32,83 @@ of any type.
3232

3333
These device plugins use `Netmiko <https://github.com/ktbyers/netmiko>`_
3434
library, which in turn uses `Paramiko` library to access and configure
35-
the switches via SSH protocol.
35+
the switches via the SSH protocol.
36+
37+
Cisco Nexus (netmiko_cisco_nxos)
38+
--------------------------------
39+
40+
Known working firmware versions: 10.3.7
41+
42+
Notes:
43+
44+
* Default state for switches is well suited for networking-generic-switch
45+
as long as SSH is utilized *and* the underlying role provided to the
46+
account permits configuration of switchports.
47+
* Pre-configuration of upstream network trunk ports to the neutron networking
48+
nodes is advisable, however the ``ngs_trunk_ports`` setting should be
49+
suitable for most users as well.
50+
* Use of an "enable" secret through the ``secret`` configuration option has
51+
not been tested.
52+
53+
Dell Force10 OS9 (netmiko_dell_force10)
54+
---------------------------------------
55+
56+
Known working firmware versions: 9.13.0.0
57+
58+
Notes:
59+
60+
* Dell Force10 Simulator for 9.13.0 lacks the ability to set a switchport
61+
mode to trunk, which prevents automated or even semi-automated testing.
62+
That being said, creating VLANs and tagging/untagging works as expected.
63+
* Uplink switchports to the rest of the network fabric must be configured in
64+
advance if the ``ngs_trunk_ports`` switch device level configuration
65+
option is *not* utilized.
66+
* Use of SSH is expected and must be configured on the remote switch.
67+
* Set each port to "switchport" to enable L2 switchport mode.
68+
* Use of an "enable" secret through the switch level configuration option
69+
``secret`` was the tested path. Depending on precise switch configuration
70+
and access control modeling, it may be possible to use without an enable
71+
secret, but that has not been tested.
72+
73+
Known Issues:
74+
75+
* `bug 2100641 <https://bugs.launchpad.net/ironic/+bug/2100641>`_ is
76+
alieviated by setting a port to "switchport" *before* attempting to utilize
77+
networking-generic-switch.
78+
79+
Dell Force10 OS10 (netmiko_dell_os10)
80+
-------------------------------------
81+
82+
Known working firmware version: 10.6.0.2.74
83+
84+
Notes:
85+
86+
* Uplink switchports may need to be configured as Trunk ports prior to the
87+
use of networking-generic-switch through a "switchport mode trunk" command.
88+
Further specific trunk configuration may be necessary, however NGS can
89+
leverage the ``ngs_trunk_ports`` configuration option and does appropriately
90+
tag switchports as permitted when creating/deleting attachments.
91+
* Password authentication for networking-generic-switch needs to be setup in
92+
advance, specifically "ip ssh server enable" and
93+
"ip ssh server password-authentication" commands.
94+
* This driver was tested *without* the use of an enable secret to
95+
permit a higher level of configuration access within the Switch.
96+
97+
Sonic - Community Distribution (netmiko_sonic)
98+
----------------------------------------------
99+
100+
Known working firmware version: master branch - March 2025
101+
102+
Notes:
103+
104+
* The driver expects to be able to SSH into the switch running
105+
SONiC, execute sudo, and then execute configuration commands.
106+
* Ports *must* be in Layer-2 mode. As such,
107+
``sudo config interface ip remove $INTERFACE $IP_ADDRESS/$CIDR``
108+
and ``sudo config switchport mode access $INTERFACE`` commands
109+
may be required.
110+
* Uplink switch ports should be configured in advance with the
111+
``sudo config switchport mode trunk $INTERFACE`` command.
112+
Testing for the configuraiton utilized this advanced state
113+
configuration of the trunk uplink ports with the ``ngs_trunk_ports``
114+
configuration option for Networking-Generic-Switch.

networking_generic_switch/devices/__init__.py

Lines changed: 75 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,14 @@ def __init__(self, device_cfg, device_name=""):
112112

113113
self._validate_network_name_format()
114114

115+
@property
116+
def support_trunk_on_ports(self):
117+
return False
118+
119+
@property
120+
def support_trunk_on_bond_ports(self):
121+
return False
122+
115123
def _validate_network_name_format(self):
116124
"""Validate the network name format configuration option."""
117125
network_name_format = self.ngs_config['ngs_network_name_format']
@@ -223,17 +231,78 @@ def del_network(self, segmentation_id, network_id):
223231
pass
224232

225233
@abc.abstractmethod
226-
def plug_port_to_network(self, port_id, segmentation_id):
234+
def plug_port_to_network(self, port_id, segmentation_id,
235+
trunk_details=None):
236+
"""Plug port into network.
237+
238+
:param port_id: Then name of the switch interface
239+
:param segmentation_id: VLAN identifier of the network used as access
240+
or native VLAN for port.
241+
242+
:param trunk_details: trunk information if port is a part of trunk
243+
"""
227244
pass
228245

229246
@abc.abstractmethod
230-
def delete_port(self, port_id, segmentation_id):
247+
def delete_port(self, port_id, segmentation_id, trunk_details=None):
248+
"""Delete port from specific network.
249+
250+
:param port_id: Then name of the switch interface
251+
:param segmentation_id: VLAN identifier of the network used as access
252+
or native VLAN for port.
253+
254+
:param trunk_details: trunk information if port is a part of trunk
255+
"""
231256
pass
232257

233-
def plug_bond_to_network(self, bond_id, segmentation_id):
258+
def plug_bond_to_network(self, bond_id, segmentation_id,
259+
trunk_details=None):
260+
"""Plug bond port into network.
261+
262+
:param port_id: Then name of the switch interface
263+
:param segmentation_id: VLAN identifier of the network used as access
264+
or native VLAN for port.
265+
266+
:param trunk_details: trunk information if port is a part of trunk
267+
"""
268+
kwargs = {}
269+
if trunk_details:
270+
kwargs["trunk_details"] = trunk_details
234271
# Fall back to interface method.
235-
return self.plug_port_to_network(bond_id, segmentation_id)
272+
return self.plug_port_to_network(bond_id, segmentation_id, **kwargs)
236273

237-
def unplug_bond_from_network(self, bond_id, segmentation_id):
274+
def unplug_bond_from_network(self, bond_id, segmentation_id,
275+
trunk_details=None):
276+
"""Unplug bond port from network.
277+
278+
:param port_id: Then name of the switch interface
279+
:param segmentation_id: VLAN identifier of the network used as access
280+
or native VLAN for port.
281+
282+
:param trunk_details: trunk information if port is a part of trunk
283+
"""
284+
kwargs = {}
285+
if trunk_details:
286+
kwargs["trunk_details"] = trunk_details
238287
# Fall back to interface method.
239-
return self.delete_port(bond_id, segmentation_id)
288+
return self.delete_port(bond_id, segmentation_id, **kwargs)
289+
290+
def add_subports_on_trunk(self, binding_profile, port_id, subports):
291+
"""Allow subports on trunk
292+
293+
:param binding_profile: Binding profile of parent port
294+
:param port_id: The name of the switch port from
295+
Local Link Information
296+
:param subports: List with subports objects.
297+
"""
298+
pass
299+
300+
def del_subports_on_trunk(self, binding_profile, port_id, subports):
301+
"""Allow subports on trunk
302+
303+
:param binding_profile: Binding profile of parent port
304+
:param port_id: The name of the switch port from
305+
Local Link Information
306+
:param subports: List with subports objects.
307+
"""
308+
pass

0 commit comments

Comments
 (0)