Skip to content

Commit a585f35

Browse files
authored
Merge pull request #105 from stackhpc/upstream/master-2025-03-10
Synchronise master with upstream
2 parents 3b1bf80 + 7528b81 commit a585f35

File tree

3 files changed

+97
-107
lines changed

3 files changed

+97
-107
lines changed

networking_generic_switch/devices/netmiko_devices/__init__.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,14 @@
1515
import atexit
1616
import contextlib
1717
import functools
18+
import hashlib
1819
import uuid
1920

2021
import netmiko
2122
from oslo_config import cfg
2223
from oslo_log import log as logging
23-
import paramiko
24+
from paramiko import PKey as _pkey # noqa - This is for a monkeypatch
25+
import paramiko # noqa - Must load after the patch
2426
import tenacity
2527
from tooz import coordination
2628

@@ -30,6 +32,11 @@
3032
from networking_generic_switch import exceptions as exc
3133
from networking_generic_switch import locking as ngs_lock
3234

35+
# NOTE(TheJulia) monkey patch paramiko's get_finerprint function
36+
# to use sha256 instead of md5, since Paramiko's maintainer doesn't
37+
# seem to be concerned about FIPS compliance.
38+
_pkey.get_fingerprint = lambda x: hashlib.sha256(x.asbytes()).digest()
39+
3340
LOG = logging.getLogger(__name__)
3441
CONF = cfg.CONF
3542

networking_generic_switch/generic_switch_mech.py

Lines changed: 38 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -342,7 +342,7 @@ def update_port_postcommit(self, context):
342342
state changes that it does not know or care about.
343343
"""
344344
port = context.current
345-
network = context.network.current
345+
segment = context.top_bound_segment
346346
if self._is_port_bound(port):
347347
binding_profile = port['binding:profile']
348348
local_link_information = binding_profile.get(
@@ -359,7 +359,7 @@ def update_port_postcommit(self, context):
359359
return
360360
# If binding has already succeeded, we should have valid links
361361
# at this point, but check just in case.
362-
if not self._is_link_valid(port, network):
362+
if not self._is_link_valid(port, segment):
363363
return
364364
is_802_3ad = self._is_802_3ad(port)
365365
for link in local_link_information:
@@ -371,7 +371,7 @@ def update_port_postcommit(self, context):
371371
ngs_mac_address=switch_id)
372372

373373
# If segmentation ID is None, set vlan 1
374-
segmentation_id = network.get('provider:segmentation_id') or 1
374+
segmentation_id = segment.get(api.SEGMENTATION_ID) or 1
375375
trunk_details = port.get('trunk_details', {})
376376
LOG.debug("Putting switch port %(switch_port)s on "
377377
"%(switch_info)s in vlan %(segmentation_id)s",
@@ -411,10 +411,10 @@ def update_port_postcommit(self, context):
411411
GENERIC_SWITCH_ENTITY)
412412
elif self._is_port_bound(context.original):
413413
# The port has been unbound. This will cause the local link
414-
# information to be lost, so remove the port from the network on
414+
# information to be lost, so remove the port from the segment on
415415
# the switch now while we have the required information.
416-
self._unplug_port_from_network(context.original,
417-
context.network.current)
416+
self._unplug_port_from_segment(context.original,
417+
context.original_top_bound_segment)
418418

419419
def delete_port_precommit(self, context):
420420
"""Delete resources of a port.
@@ -443,7 +443,7 @@ def delete_port_postcommit(self, context):
443443

444444
port = context.current
445445
if self._is_port_bound(port):
446-
self._unplug_port_from_network(port, context.network.current)
446+
self._unplug_port_from_segment(port, context.top_bound_segment)
447447

448448
def _is_vlan_translation_required(self, trunk_details):
449449
"""Check if vlan translation is required to configure specific trunk.
@@ -500,34 +500,50 @@ def bind_port(self, context):
500500
# For more info please read docstring.
501501

502502
port = context.current
503-
network = context.network.current
504503
binding_profile = port['binding:profile']
505504
local_link_information = binding_profile.get('local_link_information')
506505

507506
if self._is_port_supported(port) and local_link_information:
507+
# Filter segments where port is already assigned to subnet(s)
508+
subnets = []
509+
for fixed_ip in port.get('fixed_ips', []):
510+
subnet_id = fixed_ip.get('subnet_id')
511+
if subnet_id:
512+
subnets.append(context._plugin.get_subnet(
513+
context.plugin_context,
514+
subnet_id))
515+
segments = []
516+
if len(subnets) > 0:
517+
for segment in context.segments_to_bind:
518+
for subnet in subnets:
519+
segment_id = subnet.get('segment_id')
520+
if segment_id is None or segment_id == segment[api.ID]:
521+
segments.append(segment)
522+
else:
523+
segments = context.segments_to_bind
524+
508525
# NOTE(jamesdenton): If any link of the port is invalid, none
509526
# of the links should be processed.
510-
if not self._is_link_valid(port, network):
527+
if not self._is_link_valid(port, segments[0]):
511528
return
512529

513-
segments = context.segments_to_bind
514530
context.set_binding(segments[0][api.ID],
515531
portbindings.VIF_TYPE_OTHER, {})
516532

517533
provisioning_blocks.add_provisioning_component(
518534
context._plugin_context, port['id'], resources.PORT,
519535
GENERIC_SWITCH_ENTITY)
520536

521-
def _is_link_valid(self, port, network):
522-
"""Return whether a link references valid switch and physnet.
537+
def _is_link_valid(self, port, segment):
538+
"""Return whether a link references valid switch and segment.
523539
524540
If the local link information refers to a switch that is not
525541
known to NGS or the switch is not associated with the respective
526542
physnet, the port will not be processed and no exception will
527543
be raised.
528544
529545
:param port: The port to check
530-
:param network: the network mapped to physnet
546+
:param segment: The segment to check against
531547
:returns: Whether the link refers to a configured switch and/or switch
532548
is associated with physnet
533549
"""
@@ -550,9 +566,9 @@ def _is_link_valid(self, port, network):
550566
'device': switch_info})
551567
return False
552568

553-
physnet = network['provider:physical_network']
569+
physnet = segment.get(api.PHYSICAL_NETWORK)
554570
switch_physnets = switch._get_physical_networks()
555-
segmentation_id = network.get('provider:segmentation_id') or 1
571+
segmentation_id = segment.get(api.SEGMENTATION_ID) or 1
556572

557573
if switch_physnets and physnet not in switch_physnets:
558574
LOG.error("Cannot bind port %(port)s as device %(device)s "
@@ -616,15 +632,15 @@ def _is_802_3ad(port):
616632
return False
617633
return local_group_information.get('bond_mode') in ['4', '802.3ad']
618634

619-
def _unplug_port_from_network(self, port, network):
620-
"""Unplug a port from a network.
635+
def _unplug_port_from_segment(self, port, segment):
636+
"""Unplug a port from a segment.
621637
622638
If the configuration required to unplug the port is not present
623639
(e.g. local link information), the port will not be unplugged and no
624640
exception will be raised.
625641
626642
:param port: The port to unplug
627-
:param network: The network from which to unplug the port
643+
:param segment: The segment from which to unplug the port
628644
"""
629645
binding_profile = port['binding:profile']
630646
local_link_information = binding_profile.get('local_link_information')
@@ -642,7 +658,7 @@ def _unplug_port_from_network(self, port, network):
642658
continue
643659
port_id = link.get('port_id')
644660
# If segmentation ID is None, set vlan 1
645-
segmentation_id = network.get('provider:segmentation_id') or 1
661+
segmentation_id = segment.get(api.SEGMENTATION_ID) or 1
646662
LOG.debug("Unplugging port %(port)s on %(switch_info)s from vlan: "
647663
"%(segmentation_id)s",
648664
{'port': port_id, 'switch_info': switch_info,
@@ -656,12 +672,13 @@ def _unplug_port_from_network(self, port, network):
656672
LOG.error("Failed to unplug port %(port_id)s "
657673
"on device: %(switch)s from network %(net_id)s "
658674
"reason: %(exc)s",
659-
{'port_id': port['id'], 'net_id': network['id'],
675+
{'port_id': port['id'],
676+
'net_id': segment['network_id'],
660677
'switch': switch_info, 'exc': e})
661678
raise e
662679
LOG.info('Port %(port_id)s has been unplugged from network '
663680
'%(net_id)s on device %(device)s',
664-
{'port_id': port['id'], 'net_id': network['id'],
681+
{'port_id': port['id'], 'net_id': segment['network_id'],
665682
'device': switch_info})
666683

667684
def _get_devices_by_physnet(self, physnet):

0 commit comments

Comments
 (0)