Skip to content

Commit ef64519

Browse files
authored
Merge pull request #165 from stackhpc/upstream/2023.1-2024-07-15
Synchronise 2023.1 with upstream
2 parents 1530d2f + 82ece4f commit ef64519

File tree

20 files changed

+283
-81
lines changed

20 files changed

+283
-81
lines changed

neutron/agent/ovn/metadata/agent.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -309,13 +309,33 @@ def _load_config(self):
309309
LOG.debug("Loaded chassis name %s (UUID: %s) and ovn bridge %s.",
310310
self.chassis, self.chassis_id, self.ovn_bridge)
311311

312+
def _update_chassis_config(self):
313+
"""Update the Chassis register information
314+
315+
This method should be called once the Metadata Agent has been
316+
registered (method ``register_metadata_agent`` has been called) and
317+
the corresponding Chasis or Chassis_Private register has been
318+
created/updated. The Chassis table is used in an event when OVN does
319+
not have the Chassis_Private.
320+
"""
321+
external_ids = {ovn_const.OVN_AGENT_OVN_BRIDGE: self.ovn_bridge}
322+
if self.has_chassis_private:
323+
self.sb_idl.db_set(
324+
'Chassis_Private', self.chassis,
325+
('external_ids', external_ids)).execute(check_error=True)
326+
else:
327+
self.sb_idl.db_set(
328+
'Chassis', self.chassis,
329+
('external_ids', external_ids)).execute(check_error=True)
330+
312331
@_sync_lock
313332
def resync(self):
314333
"""Resync the agent.
315334
316335
Reload the configuration and sync the agent again.
317336
"""
318337
self._load_config()
338+
self._update_chassis_config()
319339
self.sync()
320340

321341
def start(self):
@@ -361,6 +381,7 @@ def start(self):
361381

362382
# Register the agent with its corresponding Chassis
363383
self.register_metadata_agent()
384+
self._update_chassis_config()
364385

365386
self._proxy.wait()
366387

neutron/api/rpc/agentnotifiers/dhcp_rpc_agent_api.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,7 @@ def _after_router_interface_deleted(self, resource, event, trigger,
284284
port = payload.metadata.get('port')
285285
self._notify_agents(payload.context, 'port_delete_end',
286286
{'port_id': port['id'],
287+
'fixed_ips': port['fixed_ips'],
287288
'network_id': port['network_id']},
288289
port['network_id'])
289290

neutron/common/_constants.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,3 +89,6 @@
8989

9090
# Neutron-lib defines this with a /64 but it should be /128
9191
METADATA_V6_CIDR = constants.METADATA_V6_IP + '/128'
92+
93+
# TODO(ralonsoh): move this constant to neutron_lib.plugins.ml2.ovs_constants
94+
DEFAULT_BR_INT = 'br-int'

neutron/common/ovn/constants.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,8 @@
7171
OVN_NAME_PREFIX = 'neutron-'
7272
OVN_HA_CH_GROUP_EXTPORT_PREFIX = 'neutron-extport-'
7373

74+
OVN_DATAPATH_TYPE = 'datapath-type'
75+
7476
# TODO(froyo): Move this to neutron-lib as soon as possible, and when a new
7577
# release is created and pointed to in the requirements remove this code
7678
OVN_LB_HM_PORT_DISTRIBUTED = 'ovn-lb-hm:distributed'
@@ -83,6 +85,7 @@
8385
OVN_AGENT_NEUTRON_SB_CFG_KEY = 'neutron:ovn-neutron-agent-sb-cfg'
8486
OVN_AGENT_NEUTRON_DESC_KEY = 'neutron:description-neutron-agent'
8587
OVN_AGENT_NEUTRON_ID_KEY = 'neutron:ovn-neutron-agent-id'
88+
OVN_AGENT_OVN_BRIDGE = 'neutron:ovn-bridge'
8689
OVN_CONTROLLER_AGENT = 'OVN Controller agent'
8790
OVN_CONTROLLER_GW_AGENT = 'OVN Controller Gateway agent'
8891
OVN_METADATA_AGENT = 'OVN Metadata agent'

neutron/common/ovn/utils.py

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
import tenacity
4141

4242
from neutron._i18n import _
43+
from neutron.common import _constants as n_const
4344
from neutron.common.ovn import constants
4445
from neutron.common.ovn import exceptions as ovn_exc
4546
from neutron.common import utils as common_utils
@@ -367,7 +368,7 @@ def validate_and_get_data_from_binding_profile(port):
367368
if (constants.OVN_PORT_BINDING_PROFILE not in port or
368369
not validators.is_attr_set(
369370
port[constants.OVN_PORT_BINDING_PROFILE])):
370-
BPInfo({}, None, [])
371+
return BPInfo({}, None, [])
371372
param_set = {}
372373
param_dict = {}
373374
vnic_type = port.get(portbindings.VNIC_TYPE, portbindings.VNIC_NORMAL)
@@ -718,6 +719,32 @@ def get_ovn_cms_options(chassis):
718719
constants.OVN_CMS_OPTIONS, '').split(',')]
719720

720721

722+
def get_ovn_bridge_from_chassis(chassis):
723+
"""Return the OVN bridge used by the local OVN controller
724+
725+
This information is stored in the Chassis or Chassis_Private register by
726+
the OVN Metadata agent. The default value returned, if not present, is
727+
"br-int".
728+
NOTE: the default value is not reading the local ``OVS.integration_bridge``
729+
configuration knob, that could be different.
730+
"""
731+
return (chassis.external_ids.get(constants.OVN_AGENT_OVN_BRIDGE) or
732+
n_const.DEFAULT_BR_INT)
733+
734+
735+
def get_datapath_type(hostname, sb_idl):
736+
"""Return the local OVS integration bridge datapath type
737+
738+
If the datapath type is not stored in the ``Chassis`` register or
739+
the register is still not created, the default value returned is "".
740+
"""
741+
chassis = sb_idl.db_find(
742+
'Chassis', ('hostname', '=', hostname)).execute(check_error=True)
743+
return (
744+
chassis[0].get('other_config', {}).get(constants.OVN_DATAPATH_TYPE, '')
745+
if chassis else '')
746+
747+
721748
def is_gateway_chassis(chassis):
722749
"""Check if the given chassis is a gateway chassis"""
723750
return constants.CMS_OPT_CHASSIS_AS_GW in get_ovn_cms_options(chassis)

neutron/db/models_v2.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -308,7 +308,7 @@ class SubnetPool(standard_attr.HasStandardAttributes, model_base.BASEV2,
308308
lazy='subquery')
309309
rbac_entries = sa.orm.relationship(rbac_db_models.SubnetPoolRBAC,
310310
backref='subnetpools',
311-
lazy='joined',
311+
lazy='selectin',
312312
cascade='all, delete, delete-orphan')
313313
api_collections = [subnetpool_def.COLLECTION_NAME]
314314
collection_resource_map = {subnetpool_def.COLLECTION_NAME:

neutron/plugins/ml2/drivers/mech_sriov/agent/sriov_nic_agent.py

Lines changed: 32 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -112,17 +112,39 @@ def network_update(self, context, **kwargs):
112112
def binding_activate(self, context, **kwargs):
113113
if kwargs.get('host') != self.agent.conf.host:
114114
return
115-
LOG.debug("binding activate for port %s", kwargs.get('port_id'))
116-
device_details = self.agent.get_device_details_from_port_id(
117-
kwargs.get('port_id'))
118-
mac = device_details.get('mac_address')
119-
binding_profile = device_details.get('profile')
120-
if binding_profile:
121-
pci_slot = binding_profile.get('pci_slot')
122-
self.agent.activated_bindings.add((mac, pci_slot))
115+
116+
port_id = kwargs.get('port_id')
117+
118+
def _is_port_id_in_network(network_port, port_id):
119+
for network_id, ports in network_port.items():
120+
for port in ports:
121+
if port['port_id'] == port_id:
122+
return True
123+
return False
124+
125+
is_port_id_sriov = _is_port_id_in_network(
126+
self.agent.network_ports, port_id
127+
)
128+
129+
if is_port_id_sriov:
130+
LOG.debug("binding activate for port %s", port_id)
131+
device_details = self.agent.get_device_details_from_port_id(
132+
port_id)
133+
mac = device_details.get('mac_address')
134+
binding_profile = device_details.get('profile')
135+
if binding_profile:
136+
pci_slot = binding_profile.get('pci_slot')
137+
self.agent.activated_bindings.add((mac, pci_slot))
138+
else:
139+
LOG.warning(
140+
"binding_profile not found for port %s.",
141+
port_id
142+
)
123143
else:
124-
LOG.warning("binding_profile not found for port %s.",
125-
kwargs.get('port_id'))
144+
LOG.warning(
145+
"This port is not SRIOV, skip binding for port %s.",
146+
port_id
147+
)
126148

127149
def binding_deactivate(self, context, **kwargs):
128150
if kwargs.get('host') != self.agent.conf.host:

neutron/plugins/ml2/drivers/ovn/db_migration.py

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
1212
# License for the specific language governing permissions and limitations
1313
# under the License.
14+
import copy
1415

1516
from neutron_lib.api.definitions import portbindings as pb_api
1617
from neutron_lib import context as n_context
@@ -20,6 +21,7 @@
2021
from oslo_log import log as logging
2122
from sqlalchemy.orm import exc as sqla_exc
2223

24+
from neutron.common import _constants as n_const
2325
from neutron.db.models.plugins.ml2 import geneveallocation
2426
from neutron.db.models.plugins.ml2 import vxlanallocation
2527
from neutron.objects import network as network_obj
@@ -29,10 +31,6 @@
2931

3032
LOG = logging.getLogger(__name__)
3133

32-
VIF_DETAILS_TO_REMOVE = (
33-
pb_api.VIF_DETAILS_BRIDGE_NAME,
34-
)
35-
3634

3735
def migrate_neutron_database_to_ovn():
3836
"""Change DB content from OVS to OVN mech driver.
@@ -74,18 +72,22 @@ def migrate_neutron_database_to_ovn():
7472
with db_api.CONTEXT_WRITER.using(ctx):
7573
pb = port_obj.PortBinding.get_object(ctx, port_id=port_id,
7674
host=host)
77-
if not pb or not pb.vif_details:
75+
if not pb:
7876
continue
7977

80-
vif_details = pb.vif_details.copy()
81-
for detail in VIF_DETAILS_TO_REMOVE:
82-
try:
83-
del vif_details[detail]
84-
except KeyError:
85-
pass
86-
if vif_details == pb.vif_details:
78+
# Update the OVS bridge name in the VIF details: now all
79+
# port are directly connected to the integration bridge.
80+
# Because the name of each host integration bridge is not
81+
# know by the Neutron API at this point, the default value
82+
# "br-int" will be used.
83+
# The OVS datapath type is unchanged.
84+
vif_details = copy.deepcopy(pb.vif_details) or {}
85+
if (vif_details.get(pb_api.VIF_DETAILS_BRIDGE_NAME) ==
86+
n_const.DEFAULT_BR_INT):
8787
continue
8888

89+
vif_details[pb_api.VIF_DETAILS_BRIDGE_NAME] = (
90+
n_const.DEFAULT_BR_INT)
8991
pb.vif_details = vif_details
9092
pb.update()
9193
except (exceptions.ObjectNotFound,

neutron/plugins/ml2/drivers/ovn/mech_driver/mech_driver.py

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,7 @@ def get_supported_vif_types(self):
190190
vif_types = set()
191191
for ch in self.sb_ovn.chassis_list().execute(check_error=True):
192192
other_config = ovn_utils.get_ovn_chassis_other_config(ch)
193-
dp_type = other_config.get('datapath-type', '')
193+
dp_type = other_config.get(ovn_const.OVN_DATAPATH_TYPE, '')
194194
if dp_type == ovn_const.CHASSIS_DATAPATH_NETDEV:
195195
vif_types.add(portbindings.VIF_TYPE_VHOST_USER)
196196
else:
@@ -989,7 +989,7 @@ def bind_port(self, context):
989989
return
990990
chassis = agent.chassis
991991
other_config = ovn_utils.get_ovn_chassis_other_config(chassis)
992-
datapath_type = other_config.get('datapath-type', '')
992+
datapath_type = other_config.get(ovn_const.OVN_DATAPATH_TYPE, '')
993993
iface_types = other_config.get('iface-types', '')
994994
iface_types = iface_types.split(',') if iface_types else []
995995
chassis_physnets = self.sb_ovn._get_chassis_physnets(chassis)
@@ -1036,13 +1036,25 @@ def bind_port(self, context):
10361036
vif_type = portbindings.VIF_TYPE_VHOST_USER
10371037
port[portbindings.VIF_DETAILS].update({
10381038
portbindings.VHOST_USER_SOCKET: vhost_user_socket})
1039-
vif_details = dict(self.vif_details[vif_type])
1039+
vif_details = copy.deepcopy(self.vif_details[vif_type])
10401040
vif_details[portbindings.VHOST_USER_SOCKET] = (
10411041
vhost_user_socket)
10421042
else:
10431043
vif_type = portbindings.VIF_TYPE_OVS
1044-
vif_details = self.vif_details[vif_type]
1044+
vif_details = copy.deepcopy(self.vif_details[vif_type])
10451045

1046+
if self.agent_chassis_table == 'Chassis_Private':
1047+
chassis_to_retrieve = agent.chassis_private
1048+
else:
1049+
chassis_to_retrieve = agent.chassis
1050+
ovn_bridge = ovn_utils.get_ovn_bridge_from_chassis(
1051+
chassis_to_retrieve)
1052+
1053+
dp_type = ovn_utils.get_datapath_type(bind_host, self.sb_ovn)
1054+
vif_details.update({
1055+
portbindings.VIF_DETAILS_BRIDGE_NAME: ovn_bridge,
1056+
portbindings.OVS_DATAPATH_TYPE: dp_type,
1057+
})
10461058
context.set_binding(segment_to_bind[api.ID], vif_type,
10471059
vif_details)
10481060
break

neutron/tests/functional/agent/ovn/metadata/test_metadata_agent.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,11 @@ def _start_metadata_agent(self):
110110
with mock.patch.object(metadata_server.UnixDomainMetadataProxy,
111111
'wait'):
112112
agt.start()
113+
external_ids = agt.sb_idl.db_get(
114+
'Chassis_Private', agt.chassis, 'external_ids').execute(
115+
check_error=True)
116+
self.assertEqual(external_ids[ovn_const.OVN_AGENT_OVN_BRIDGE],
117+
self.OVN_BRIDGE)
113118

114119
# Metadata agent will open connections to OVS and SB databases.
115120
# Close connections to them when the test ends,

0 commit comments

Comments
 (0)