[OVN] Add the bridge name and datapath type to the port VIF details
Same as in ML2/OVS, the ML2/OVN mechanism driver adds to the port VIF details dictionary the OVS bridge the port is connected to and the integration bridge datapath type. Closes-Bug: #2045889 Change-Id: Ifda46c42b9506449a58fbaf312cc71c72d9cf2df
This commit is contained in:
parent
97b84180b2
commit
baaf240ce3
@ -370,6 +370,18 @@ class MetadataAgent(object):
|
|||||||
LOG.debug("Loaded chassis name %s (UUID: %s) and ovn bridge %s.",
|
LOG.debug("Loaded chassis name %s (UUID: %s) and ovn bridge %s.",
|
||||||
self.chassis, self.chassis_id, self.ovn_bridge)
|
self.chassis, self.chassis_id, self.ovn_bridge)
|
||||||
|
|
||||||
|
def _update_chassis_private_config(self):
|
||||||
|
"""Update the Chassis_Private register information
|
||||||
|
|
||||||
|
This method should be called once the Metadata Agent has been
|
||||||
|
registered (method ``register_metadata_agent`` has been called) and
|
||||||
|
the corresponding Chassis_Private register has been created/updated.
|
||||||
|
"""
|
||||||
|
external_ids = {ovn_const.OVN_AGENT_OVN_BRIDGE: self.ovn_bridge}
|
||||||
|
self.sb_idl.db_set(
|
||||||
|
'Chassis_Private', self.chassis,
|
||||||
|
('external_ids', external_ids)).execute(check_error=True)
|
||||||
|
|
||||||
@_sync_lock
|
@_sync_lock
|
||||||
def resync(self):
|
def resync(self):
|
||||||
"""Resync the agent.
|
"""Resync the agent.
|
||||||
@ -377,6 +389,7 @@ class MetadataAgent(object):
|
|||||||
Reload the configuration and sync the agent again.
|
Reload the configuration and sync the agent again.
|
||||||
"""
|
"""
|
||||||
self._load_config()
|
self._load_config()
|
||||||
|
self._update_chassis_private_config()
|
||||||
self.sync()
|
self.sync()
|
||||||
|
|
||||||
def start(self):
|
def start(self):
|
||||||
@ -409,6 +422,7 @@ class MetadataAgent(object):
|
|||||||
|
|
||||||
# Register the agent with its corresponding Chassis
|
# Register the agent with its corresponding Chassis
|
||||||
self.register_metadata_agent()
|
self.register_metadata_agent()
|
||||||
|
self._update_chassis_private_config()
|
||||||
|
|
||||||
self._proxy.wait()
|
self._proxy.wait()
|
||||||
|
|
||||||
|
@ -92,3 +92,7 @@ METADATA_V6_CIDR = constants.METADATA_V6_IP + '/128'
|
|||||||
|
|
||||||
# TODO(haleyb): move this constant to neutron_lib.constants
|
# TODO(haleyb): move this constant to neutron_lib.constants
|
||||||
IPV4_MIN_MTU = 68
|
IPV4_MIN_MTU = 68
|
||||||
|
|
||||||
|
|
||||||
|
# TODO(ralonsoh): move this constant to neutron_lib.plugins.ml2.ovs_constants
|
||||||
|
DEFAULT_BR_INT = 'br-int'
|
||||||
|
@ -72,6 +72,8 @@ OVN_NAME_PREFIX = 'neutron-'
|
|||||||
OVN_HA_CH_GROUP_EXTPORT_PREFIX = 'neutron-extport-'
|
OVN_HA_CH_GROUP_EXTPORT_PREFIX = 'neutron-extport-'
|
||||||
OVN_METADATA_PREFIX = 'ovnmeta-'
|
OVN_METADATA_PREFIX = 'ovnmeta-'
|
||||||
|
|
||||||
|
OVN_DATAPATH_TYPE = 'datapath-type'
|
||||||
|
|
||||||
# TODO(froyo): Move this to neutron-lib as soon as possible, and when a new
|
# TODO(froyo): Move this to neutron-lib as soon as possible, and when a new
|
||||||
# release is created and pointed to in the requirements remove this code
|
# release is created and pointed to in the requirements remove this code
|
||||||
OVN_LB_HM_PORT_DISTRIBUTED = 'ovn-lb-hm:distributed'
|
OVN_LB_HM_PORT_DISTRIBUTED = 'ovn-lb-hm:distributed'
|
||||||
@ -84,6 +86,7 @@ OVN_AGENT_METADATA_ID_KEY = 'neutron:ovn-metadata-id'
|
|||||||
OVN_AGENT_NEUTRON_SB_CFG_KEY = 'neutron:ovn-neutron-agent-sb-cfg'
|
OVN_AGENT_NEUTRON_SB_CFG_KEY = 'neutron:ovn-neutron-agent-sb-cfg'
|
||||||
OVN_AGENT_NEUTRON_DESC_KEY = 'neutron:description-neutron-agent'
|
OVN_AGENT_NEUTRON_DESC_KEY = 'neutron:description-neutron-agent'
|
||||||
OVN_AGENT_NEUTRON_ID_KEY = 'neutron:ovn-neutron-agent-id'
|
OVN_AGENT_NEUTRON_ID_KEY = 'neutron:ovn-neutron-agent-id'
|
||||||
|
OVN_AGENT_OVN_BRIDGE = 'neutron:ovn-bridge'
|
||||||
OVN_CONTROLLER_AGENT = 'OVN Controller agent'
|
OVN_CONTROLLER_AGENT = 'OVN Controller agent'
|
||||||
OVN_CONTROLLER_GW_AGENT = 'OVN Controller Gateway agent'
|
OVN_CONTROLLER_GW_AGENT = 'OVN Controller Gateway agent'
|
||||||
OVN_METADATA_AGENT = 'OVN Metadata agent'
|
OVN_METADATA_AGENT = 'OVN Metadata agent'
|
||||||
|
@ -40,6 +40,7 @@ from ovsdbapp import constants as ovsdbapp_const
|
|||||||
import tenacity
|
import tenacity
|
||||||
|
|
||||||
from neutron._i18n import _
|
from neutron._i18n import _
|
||||||
|
from neutron.common import _constants as n_const
|
||||||
from neutron.common.ovn import constants
|
from neutron.common.ovn import constants
|
||||||
from neutron.common.ovn import exceptions as ovn_exc
|
from neutron.common.ovn import exceptions as ovn_exc
|
||||||
from neutron.common import utils as common_utils
|
from neutron.common import utils as common_utils
|
||||||
@ -707,6 +708,31 @@ def get_ovn_cms_options(chassis):
|
|||||||
constants.OVN_CMS_OPTIONS, '').split(',')]
|
constants.OVN_CMS_OPTIONS, '').split(',')]
|
||||||
|
|
||||||
|
|
||||||
|
def get_ovn_bridge_from_chassis_private(chassis_private):
|
||||||
|
"""Return the OVN bridge used by the local OVN controller
|
||||||
|
|
||||||
|
This information is stored in the Chassis_Private register by the OVN
|
||||||
|
Metadata agent. The default value returned, if not present, is "br-int".
|
||||||
|
NOTE: the default value is not reading the local ``OVS.integration_bridge``
|
||||||
|
configuration knob, that could be different.
|
||||||
|
"""
|
||||||
|
return (chassis_private.external_ids.get(constants.OVN_AGENT_OVN_BRIDGE) or
|
||||||
|
n_const.DEFAULT_BR_INT)
|
||||||
|
|
||||||
|
|
||||||
|
def get_datapath_type(hostname, sb_idl):
|
||||||
|
"""Return the local OVS integration bridge datapath type
|
||||||
|
|
||||||
|
If the datapath type is not stored in the ``Chassis`` register or
|
||||||
|
the register is still not created, the default value returned is "".
|
||||||
|
"""
|
||||||
|
chassis = sb_idl.db_find(
|
||||||
|
'Chassis', ('hostname', '=', hostname)).execute(check_error=True)
|
||||||
|
return (
|
||||||
|
chassis[0].get('other_config', {}).get(constants.OVN_DATAPATH_TYPE, '')
|
||||||
|
if chassis else '')
|
||||||
|
|
||||||
|
|
||||||
def is_gateway_chassis(chassis):
|
def is_gateway_chassis(chassis):
|
||||||
"""Check if the given chassis is a gateway chassis"""
|
"""Check if the given chassis is a gateway chassis"""
|
||||||
return constants.CMS_OPT_CHASSIS_AS_GW in get_ovn_cms_options(chassis)
|
return constants.CMS_OPT_CHASSIS_AS_GW in get_ovn_cms_options(chassis)
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
import copy
|
||||||
|
|
||||||
from neutron_lib.api.definitions import portbindings as pb_api
|
from neutron_lib.api.definitions import portbindings as pb_api
|
||||||
from neutron_lib import constants
|
from neutron_lib import constants
|
||||||
@ -21,6 +22,7 @@ from oslo_db import exception as db_exc
|
|||||||
from oslo_log import log as logging
|
from oslo_log import log as logging
|
||||||
from sqlalchemy.orm import exc as sqla_exc
|
from sqlalchemy.orm import exc as sqla_exc
|
||||||
|
|
||||||
|
from neutron.common import _constants as n_const
|
||||||
from neutron.db.models.plugins.ml2 import geneveallocation
|
from neutron.db.models.plugins.ml2 import geneveallocation
|
||||||
from neutron.db.models.plugins.ml2 import vxlanallocation
|
from neutron.db.models.plugins.ml2 import vxlanallocation
|
||||||
from neutron.objects import network as network_obj
|
from neutron.objects import network as network_obj
|
||||||
@ -30,10 +32,6 @@ from neutron.objects import trunk as trunk_obj
|
|||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
VIF_DETAILS_TO_REMOVE = (
|
|
||||||
pb_api.VIF_DETAILS_BRIDGE_NAME,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def migrate_neutron_database_to_ovn():
|
def migrate_neutron_database_to_ovn():
|
||||||
"""Change DB content from OVS to OVN mech driver.
|
"""Change DB content from OVS to OVN mech driver.
|
||||||
@ -75,18 +73,22 @@ def migrate_neutron_database_to_ovn():
|
|||||||
with db_api.CONTEXT_WRITER.using(ctx):
|
with db_api.CONTEXT_WRITER.using(ctx):
|
||||||
pb = port_obj.PortBinding.get_object(ctx, port_id=port_id,
|
pb = port_obj.PortBinding.get_object(ctx, port_id=port_id,
|
||||||
host=host)
|
host=host)
|
||||||
if not pb or not pb.vif_details:
|
if not pb:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
vif_details = pb.vif_details.copy()
|
# Update the OVS bridge name in the VIF details: now all
|
||||||
for detail in VIF_DETAILS_TO_REMOVE:
|
# port are directly connected to the integration bridge.
|
||||||
try:
|
# Because the name of each host integration bridge is not
|
||||||
del vif_details[detail]
|
# know by the Neutron API at this point, the default value
|
||||||
except KeyError:
|
# "br-int" will be used.
|
||||||
pass
|
# The OVS datapath type is unchanged.
|
||||||
if vif_details == pb.vif_details:
|
vif_details = copy.deepcopy(pb.vif_details) or {}
|
||||||
|
if (vif_details.get(pb_api.VIF_DETAILS_BRIDGE_NAME) ==
|
||||||
|
n_const.DEFAULT_BR_INT):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
vif_details[pb_api.VIF_DETAILS_BRIDGE_NAME] = (
|
||||||
|
n_const.DEFAULT_BR_INT)
|
||||||
pb.vif_details = vif_details
|
pb.vif_details = vif_details
|
||||||
pb.update()
|
pb.update()
|
||||||
except (exceptions.ObjectNotFound,
|
except (exceptions.ObjectNotFound,
|
||||||
|
@ -187,7 +187,7 @@ class OVNMechanismDriver(api.MechanismDriver):
|
|||||||
vif_types = set()
|
vif_types = set()
|
||||||
for ch in self.sb_ovn.chassis_list().execute(check_error=True):
|
for ch in self.sb_ovn.chassis_list().execute(check_error=True):
|
||||||
other_config = ovn_utils.get_ovn_chassis_other_config(ch)
|
other_config = ovn_utils.get_ovn_chassis_other_config(ch)
|
||||||
dp_type = other_config.get('datapath-type', '')
|
dp_type = other_config.get(ovn_const.OVN_DATAPATH_TYPE, '')
|
||||||
if dp_type == ovn_const.CHASSIS_DATAPATH_NETDEV:
|
if dp_type == ovn_const.CHASSIS_DATAPATH_NETDEV:
|
||||||
vif_types.add(portbindings.VIF_TYPE_VHOST_USER)
|
vif_types.add(portbindings.VIF_TYPE_VHOST_USER)
|
||||||
else:
|
else:
|
||||||
@ -990,7 +990,7 @@ class OVNMechanismDriver(api.MechanismDriver):
|
|||||||
return
|
return
|
||||||
chassis = agent.chassis
|
chassis = agent.chassis
|
||||||
other_config = ovn_utils.get_ovn_chassis_other_config(chassis)
|
other_config = ovn_utils.get_ovn_chassis_other_config(chassis)
|
||||||
datapath_type = other_config.get('datapath-type', '')
|
datapath_type = other_config.get(ovn_const.OVN_DATAPATH_TYPE, '')
|
||||||
iface_types = other_config.get('iface-types', '')
|
iface_types = other_config.get('iface-types', '')
|
||||||
iface_types = iface_types.split(',') if iface_types else []
|
iface_types = iface_types.split(',') if iface_types else []
|
||||||
chassis_physnets = self.sb_ovn._get_chassis_physnets(chassis)
|
chassis_physnets = self.sb_ovn._get_chassis_physnets(chassis)
|
||||||
@ -1037,7 +1037,7 @@ class OVNMechanismDriver(api.MechanismDriver):
|
|||||||
vif_type = portbindings.VIF_TYPE_VHOST_USER
|
vif_type = portbindings.VIF_TYPE_VHOST_USER
|
||||||
port[portbindings.VIF_DETAILS].update({
|
port[portbindings.VIF_DETAILS].update({
|
||||||
portbindings.VHOST_USER_SOCKET: vhost_user_socket})
|
portbindings.VHOST_USER_SOCKET: vhost_user_socket})
|
||||||
vif_details = dict(self.vif_details[vif_type])
|
vif_details = copy.deepcopy(self.vif_details[vif_type])
|
||||||
vif_details[portbindings.VHOST_USER_SOCKET] = (
|
vif_details[portbindings.VHOST_USER_SOCKET] = (
|
||||||
vhost_user_socket)
|
vhost_user_socket)
|
||||||
elif (vnic_type == portbindings.VNIC_VIRTIO_FORWARDER):
|
elif (vnic_type == portbindings.VNIC_VIRTIO_FORWARDER):
|
||||||
@ -1046,15 +1046,22 @@ class OVNMechanismDriver(api.MechanismDriver):
|
|||||||
vif_type = portbindings.VIF_TYPE_AGILIO_OVS
|
vif_type = portbindings.VIF_TYPE_AGILIO_OVS
|
||||||
port[portbindings.VIF_DETAILS].update({
|
port[portbindings.VIF_DETAILS].update({
|
||||||
portbindings.VHOST_USER_SOCKET: vhost_user_socket})
|
portbindings.VHOST_USER_SOCKET: vhost_user_socket})
|
||||||
vif_details = dict(self.vif_details[vif_type])
|
vif_details = copy.deepcopy(self.vif_details[vif_type])
|
||||||
vif_details[portbindings.VHOST_USER_SOCKET] = (
|
vif_details[portbindings.VHOST_USER_SOCKET] = (
|
||||||
vhost_user_socket)
|
vhost_user_socket)
|
||||||
vif_details[portbindings.VHOST_USER_MODE] = (
|
vif_details[portbindings.VHOST_USER_MODE] = (
|
||||||
portbindings.VHOST_USER_MODE_CLIENT)
|
portbindings.VHOST_USER_MODE_CLIENT)
|
||||||
else:
|
else:
|
||||||
vif_type = portbindings.VIF_TYPE_OVS
|
vif_type = portbindings.VIF_TYPE_OVS
|
||||||
vif_details = self.vif_details[vif_type]
|
vif_details = copy.deepcopy(self.vif_details[vif_type])
|
||||||
|
|
||||||
|
ovn_bridge = ovn_utils.get_ovn_bridge_from_chassis_private(
|
||||||
|
agent.chassis_private)
|
||||||
|
dp_type = ovn_utils.get_datapath_type(bind_host, self.sb_ovn)
|
||||||
|
vif_details.update({
|
||||||
|
portbindings.VIF_DETAILS_BRIDGE_NAME: ovn_bridge,
|
||||||
|
portbindings.OVS_DATAPATH_TYPE: dp_type,
|
||||||
|
})
|
||||||
context.set_binding(segment_to_bind[api.ID], vif_type,
|
context.set_binding(segment_to_bind[api.ID], vif_type,
|
||||||
vif_details)
|
vif_details)
|
||||||
break
|
break
|
||||||
|
@ -114,6 +114,11 @@ class TestMetadataAgent(base.TestOVNFunctionalBase):
|
|||||||
with mock.patch.object(metadata_server.UnixDomainMetadataProxy,
|
with mock.patch.object(metadata_server.UnixDomainMetadataProxy,
|
||||||
'wait'):
|
'wait'):
|
||||||
agt.start()
|
agt.start()
|
||||||
|
external_ids = agt.sb_idl.db_get(
|
||||||
|
'Chassis_Private', agt.chassis, 'external_ids').execute(
|
||||||
|
check_error=True)
|
||||||
|
self.assertEqual(external_ids[ovn_const.OVN_AGENT_OVN_BRIDGE],
|
||||||
|
self.OVN_BRIDGE)
|
||||||
|
|
||||||
# Metadata agent will open connections to OVS and SB databases.
|
# Metadata agent will open connections to OVS and SB databases.
|
||||||
# Close connections to them when the test ends,
|
# Close connections to them when the test ends,
|
||||||
|
@ -43,6 +43,8 @@ OVS_VIF_DETAILS = {
|
|||||||
portbindings.CAP_PORT_FILTER: True,
|
portbindings.CAP_PORT_FILTER: True,
|
||||||
portbindings.VIF_DETAILS_CONNECTIVITY: portbindings.CONNECTIVITY_L2,
|
portbindings.VIF_DETAILS_CONNECTIVITY: portbindings.CONNECTIVITY_L2,
|
||||||
portbindings.VIF_DETAILS_BOUND_DRIVERS: {'0': 'ovn'},
|
portbindings.VIF_DETAILS_BOUND_DRIVERS: {'0': 'ovn'},
|
||||||
|
portbindings.VIF_DETAILS_BRIDGE_NAME: 'br-int',
|
||||||
|
portbindings.OVS_DATAPATH_TYPE: 'system',
|
||||||
}
|
}
|
||||||
VHOSTUSER_VIF_DETAILS = {
|
VHOSTUSER_VIF_DETAILS = {
|
||||||
portbindings.CAP_PORT_FILTER: False,
|
portbindings.CAP_PORT_FILTER: False,
|
||||||
@ -50,34 +52,39 @@ VHOSTUSER_VIF_DETAILS = {
|
|||||||
'vhostuser_ovs_plug': True,
|
'vhostuser_ovs_plug': True,
|
||||||
portbindings.VIF_DETAILS_CONNECTIVITY: portbindings.CONNECTIVITY_L2,
|
portbindings.VIF_DETAILS_CONNECTIVITY: portbindings.CONNECTIVITY_L2,
|
||||||
portbindings.VIF_DETAILS_BOUND_DRIVERS: {'0': 'ovn'},
|
portbindings.VIF_DETAILS_BOUND_DRIVERS: {'0': 'ovn'},
|
||||||
|
portbindings.VIF_DETAILS_BRIDGE_NAME: 'br-int',
|
||||||
|
portbindings.OVS_DATAPATH_TYPE: 'netdev',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class TestPortBinding(base.TestOVNFunctionalBase):
|
class TestPortBinding(base.TestOVNFunctionalBase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self, **kwargs):
|
||||||
super(TestPortBinding, self).setUp()
|
super().setUp(**kwargs)
|
||||||
self.ovs_host = 'ovs-host'
|
self.ovs_host = 'ovs-host'
|
||||||
self.dpdk_host = 'dpdk-host'
|
self.dpdk_host = 'dpdk-host'
|
||||||
self.invalid_dpdk_host = 'invalid-host'
|
self.invalid_dpdk_host = 'invalid-host'
|
||||||
self.insecure_host = 'insecure-host'
|
self.insecure_host = 'insecure-host'
|
||||||
self.smartnic_dpu_host = 'smartnic-dpu-host'
|
self.smartnic_dpu_host = 'smartnic-dpu-host'
|
||||||
self.smartnic_dpu_serial = 'fake-smartnic-dpu-serial'
|
self.smartnic_dpu_serial = 'fake-smartnic-dpu-serial'
|
||||||
self.add_fake_chassis(self.ovs_host)
|
self.add_fake_chassis(
|
||||||
|
self.ovs_host,
|
||||||
|
other_config={ovn_const.OVN_DATAPATH_TYPE: 'system'})
|
||||||
self.add_fake_chassis(
|
self.add_fake_chassis(
|
||||||
self.dpdk_host,
|
self.dpdk_host,
|
||||||
other_config={'datapath-type': 'netdev',
|
other_config={ovn_const.OVN_DATAPATH_TYPE: 'netdev',
|
||||||
'iface-types': 'dummy,dummy-internal,dpdkvhostuser'})
|
'iface-types': 'dummy,dummy-internal,dpdkvhostuser'})
|
||||||
|
|
||||||
self.add_fake_chassis(
|
self.add_fake_chassis(
|
||||||
self.invalid_dpdk_host,
|
self.invalid_dpdk_host,
|
||||||
other_config={'datapath-type': 'netdev',
|
other_config={ovn_const.OVN_DATAPATH_TYPE: 'netdev',
|
||||||
'iface-types': 'dummy,dummy-internal,geneve,vxlan'})
|
'iface-types': 'dummy,dummy-internal,geneve,vxlan'})
|
||||||
self.add_fake_chassis(
|
self.add_fake_chassis(
|
||||||
self.smartnic_dpu_host,
|
self.smartnic_dpu_host,
|
||||||
other_config={ovn_const.OVN_CMS_OPTIONS: '{}={}'.format(
|
other_config={ovn_const.OVN_CMS_OPTIONS: '{}={}'.format(
|
||||||
ovn_const.CMS_OPT_CARD_SERIAL_NUMBER,
|
ovn_const.CMS_OPT_CARD_SERIAL_NUMBER,
|
||||||
self.smartnic_dpu_serial)})
|
self.smartnic_dpu_serial),
|
||||||
|
ovn_const.OVN_DATAPATH_TYPE: 'system'})
|
||||||
self.n1 = self._make_network(self.fmt, 'n1', True)
|
self.n1 = self._make_network(self.fmt, 'n1', True)
|
||||||
res = self._create_subnet(self.fmt, self.n1['network']['id'],
|
res = self._create_subnet(self.fmt, self.n1['network']['id'],
|
||||||
'10.0.0.0/24')
|
'10.0.0.0/24')
|
||||||
@ -152,9 +159,13 @@ class TestPortBinding(base.TestOVNFunctionalBase):
|
|||||||
self._verify_vif_details(port_id, self.dpdk_host, 'vhostuser',
|
self._verify_vif_details(port_id, self.dpdk_host, 'vhostuser',
|
||||||
expected_vif_details)
|
expected_vif_details)
|
||||||
|
|
||||||
|
expected_vif_details = copy.deepcopy(VHOSTUSER_VIF_DETAILS)
|
||||||
|
expected_vif_details.pop('vhostuser_mode')
|
||||||
|
expected_vif_details.pop('vhostuser_ovs_plug')
|
||||||
|
expected_vif_details[portbindings.CAP_PORT_FILTER] = True
|
||||||
port_id = self._create_or_update_port(hostname=self.invalid_dpdk_host)
|
port_id = self._create_or_update_port(hostname=self.invalid_dpdk_host)
|
||||||
self._verify_vif_details(port_id, self.invalid_dpdk_host, 'ovs',
|
self._verify_vif_details(port_id, self.invalid_dpdk_host, 'ovs',
|
||||||
OVS_VIF_DETAILS)
|
expected_vif_details)
|
||||||
|
|
||||||
def test_port_binding_create_remote_managed_port(self):
|
def test_port_binding_create_remote_managed_port(self):
|
||||||
pci_vendor_info = 'fake-pci-vendor-info'
|
pci_vendor_info = 'fake-pci-vendor-info'
|
||||||
@ -206,8 +217,12 @@ class TestPortBinding(base.TestOVNFunctionalBase):
|
|||||||
|
|
||||||
port_id = self._create_or_update_port(port_id=port_id,
|
port_id = self._create_or_update_port(port_id=port_id,
|
||||||
hostname=self.invalid_dpdk_host)
|
hostname=self.invalid_dpdk_host)
|
||||||
|
expected_vif_details = copy.deepcopy(VHOSTUSER_VIF_DETAILS)
|
||||||
|
expected_vif_details.pop('vhostuser_mode')
|
||||||
|
expected_vif_details.pop('vhostuser_ovs_plug')
|
||||||
|
expected_vif_details[portbindings.CAP_PORT_FILTER] = True
|
||||||
self._verify_vif_details(port_id, self.invalid_dpdk_host, 'ovs',
|
self._verify_vif_details(port_id, self.invalid_dpdk_host, 'ovs',
|
||||||
OVS_VIF_DETAILS)
|
expected_vif_details)
|
||||||
|
|
||||||
def test_port_binding_update_remote_managed_port(self):
|
def test_port_binding_update_remote_managed_port(self):
|
||||||
port_id = self._create_or_update_port(
|
port_id = self._create_or_update_port(
|
||||||
|
@ -181,6 +181,7 @@ class FakeOvsdbSbOvnIdl(object):
|
|||||||
self.get_extport_chassis_from_cms_options = mock.Mock(return_value=[])
|
self.get_extport_chassis_from_cms_options = mock.Mock(return_value=[])
|
||||||
self.is_col_present = mock.Mock()
|
self.is_col_present = mock.Mock()
|
||||||
self.is_col_present.return_value = False
|
self.is_col_present.return_value = False
|
||||||
|
self.db_find = mock.MagicMock()
|
||||||
self.db_set = mock.Mock()
|
self.db_set = mock.Mock()
|
||||||
self.lookup = mock.MagicMock()
|
self.lookup = mock.MagicMock()
|
||||||
self.chassis_list = mock.MagicMock()
|
self.chassis_list = mock.MagicMock()
|
||||||
@ -856,7 +857,8 @@ class FakeChassis(object):
|
|||||||
def create(attrs=None, az_list=None, chassis_as_gw=False,
|
def create(attrs=None, az_list=None, chassis_as_gw=False,
|
||||||
bridge_mappings=None, rp_bandwidths=None,
|
bridge_mappings=None, rp_bandwidths=None,
|
||||||
rp_inventory_defaults=None, rp_hypervisors=None,
|
rp_inventory_defaults=None, rp_hypervisors=None,
|
||||||
card_serial_number=None, chassis_as_extport=False):
|
card_serial_number=None, chassis_as_extport=False,
|
||||||
|
datapath_type=None):
|
||||||
cms_opts = []
|
cms_opts = []
|
||||||
if az_list:
|
if az_list:
|
||||||
cms_opts.append("%s=%s" % (ovn_const.CMS_OPT_AVAILABILITY_ZONES,
|
cms_opts.append("%s=%s" % (ovn_const.CMS_OPT_AVAILABILITY_ZONES,
|
||||||
@ -901,6 +903,9 @@ class FakeChassis(object):
|
|||||||
if bridge_mappings:
|
if bridge_mappings:
|
||||||
other_config['ovn-bridge-mappings'] = ','.join(bridge_mappings)
|
other_config['ovn-bridge-mappings'] = ','.join(bridge_mappings)
|
||||||
|
|
||||||
|
if datapath_type:
|
||||||
|
other_config[ovn_const.OVN_DATAPATH_TYPE] = datapath_type
|
||||||
|
|
||||||
chassis_attrs = {
|
chassis_attrs = {
|
||||||
'encaps': [],
|
'encaps': [],
|
||||||
'external_ids': '',
|
'external_ids': '',
|
||||||
|
@ -46,6 +46,7 @@ from oslo_utils import uuidutils
|
|||||||
from ovsdbapp.backend.ovs_idl import idlutils
|
from ovsdbapp.backend.ovs_idl import idlutils
|
||||||
from webob import exc
|
from webob import exc
|
||||||
|
|
||||||
|
from neutron.common import _constants as n_const
|
||||||
from neutron.common import config
|
from neutron.common import config
|
||||||
from neutron.common.ovn import acl as ovn_acl
|
from neutron.common.ovn import acl as ovn_acl
|
||||||
from neutron.common.ovn import constants as ovn_const
|
from neutron.common.ovn import constants as ovn_const
|
||||||
@ -76,6 +77,7 @@ from neutron.tests.unit.plugins.ml2 import test_security_group
|
|||||||
OVN_PROFILE = ovn_const.OVN_PORT_BINDING_PROFILE
|
OVN_PROFILE = ovn_const.OVN_PORT_BINDING_PROFILE
|
||||||
CLASS_PLACEMENT_REPORT = ('neutron.services.placement_report.plugin.'
|
CLASS_PLACEMENT_REPORT = ('neutron.services.placement_report.plugin.'
|
||||||
'PlacementReportPlugin')
|
'PlacementReportPlugin')
|
||||||
|
DEFAULT_DP_TYPE = 'system' # For testing, we define "system" as default.
|
||||||
|
|
||||||
OvnRevNumberRow = collections.namedtuple(
|
OvnRevNumberRow = collections.namedtuple(
|
||||||
'OvnRevNumberRow', ['created_at'])
|
'OvnRevNumberRow', ['created_at'])
|
||||||
@ -101,7 +103,7 @@ class MechDriverSetupBase(abc.ABC):
|
|||||||
self.mock_vp_parents = mock.patch.object(
|
self.mock_vp_parents = mock.patch.object(
|
||||||
ovn_utils, 'get_virtual_port_parents', return_value=None).start()
|
ovn_utils, 'get_virtual_port_parents', return_value=None).start()
|
||||||
|
|
||||||
def _add_chassis(self, nb_cfg, name=None):
|
def _add_chassis_private(self, nb_cfg, name=None):
|
||||||
chassis_private = mock.Mock()
|
chassis_private = mock.Mock()
|
||||||
chassis_private.nb_cfg = nb_cfg
|
chassis_private.nb_cfg = nb_cfg
|
||||||
chassis_private.uuid = uuid.uuid4()
|
chassis_private.uuid = uuid.uuid4()
|
||||||
@ -109,26 +111,40 @@ class MechDriverSetupBase(abc.ABC):
|
|||||||
chassis_private.nb_cfg_timestamp = timeutils.utcnow_ts() * 1000
|
chassis_private.nb_cfg_timestamp = timeutils.utcnow_ts() * 1000
|
||||||
return chassis_private
|
return chassis_private
|
||||||
|
|
||||||
def _add_chassis_agent(self, nb_cfg, agent_type, chassis_private=None):
|
def _add_chassis(self, name, hostname, external_ids=None,
|
||||||
chassis_private = chassis_private or self._add_chassis(nb_cfg)
|
other_config=None):
|
||||||
|
external_ids = external_ids or {}
|
||||||
|
other_config = other_config or {}
|
||||||
|
return mock.Mock(name=name, hostname=hostname,
|
||||||
|
external_ids=external_ids, other_config=other_config)
|
||||||
|
|
||||||
|
def _add_chassis_agent(self, nb_cfg, agent_type, chassis_private=None,
|
||||||
|
hostname=None):
|
||||||
|
chassis_private = chassis_private or self._add_chassis_private(nb_cfg)
|
||||||
|
hostname = hostname or chassis_private.name + '_host'
|
||||||
if hasattr(chassis_private, 'nb_cfg_timestamp') and isinstance(
|
if hasattr(chassis_private, 'nb_cfg_timestamp') and isinstance(
|
||||||
chassis_private.nb_cfg_timestamp, mock.Mock):
|
chassis_private.nb_cfg_timestamp, mock.Mock):
|
||||||
del chassis_private.nb_cfg_timestamp
|
del chassis_private.nb_cfg_timestamp
|
||||||
chassis_private.external_ids = {}
|
chassis_private.external_ids = {
|
||||||
chassis_private.other_config = {}
|
ovn_const.OVN_AGENT_OVN_BRIDGE: n_const.DEFAULT_BR_INT,
|
||||||
|
ovn_const.OVN_DATAPATH_TYPE: DEFAULT_DP_TYPE,
|
||||||
|
}
|
||||||
if agent_type == ovn_const.OVN_METADATA_AGENT:
|
if agent_type == ovn_const.OVN_METADATA_AGENT:
|
||||||
chassis_private.external_ids.update({
|
chassis_private.external_ids.update({
|
||||||
ovn_const.OVN_AGENT_METADATA_SB_CFG_KEY: nb_cfg,
|
ovn_const.OVN_AGENT_METADATA_SB_CFG_KEY: nb_cfg,
|
||||||
ovn_const.OVN_AGENT_METADATA_ID_KEY: str(uuid.uuid4())})
|
ovn_const.OVN_AGENT_METADATA_ID_KEY: str(uuid.uuid4())})
|
||||||
chassis_private.chassis = [chassis_private]
|
chassis_private.chassis = [self._add_chassis(chassis_private.name,
|
||||||
|
hostname)]
|
||||||
return neutron_agent.AgentCache().update(agent_type, chassis_private)
|
return neutron_agent.AgentCache().update(agent_type, chassis_private)
|
||||||
|
|
||||||
def _add_agent(self, name, nb_cfg_offset=0):
|
def _add_agent(self, name, nb_cfg_offset=0, hostname=None):
|
||||||
|
hostname = hostname or name + '_host'
|
||||||
nb_cfg = 5
|
nb_cfg = 5
|
||||||
self.mech_driver.nb_ovn.nb_global.nb_cfg = nb_cfg + nb_cfg_offset
|
self.mech_driver.nb_ovn.nb_global.nb_cfg = nb_cfg + nb_cfg_offset
|
||||||
chassis = self._add_chassis(nb_cfg, name=name)
|
chassis_private = self._add_chassis_private(nb_cfg, name=name)
|
||||||
return self._add_chassis_agent(
|
return self._add_chassis_agent(
|
||||||
nb_cfg, ovn_const.OVN_CONTROLLER_AGENT, chassis)
|
nb_cfg, ovn_const.OVN_CONTROLLER_AGENT,
|
||||||
|
chassis_private=chassis_private, hostname=hostname)
|
||||||
|
|
||||||
|
|
||||||
class TestOVNMechanismDriverBase(MechDriverSetupBase,
|
class TestOVNMechanismDriverBase(MechDriverSetupBase,
|
||||||
@ -1242,6 +1258,9 @@ class TestOVNMechanismDriver(TestOVNMechanismDriverBase):
|
|||||||
self._test_bind_port_failed([])
|
self._test_bind_port_failed([])
|
||||||
|
|
||||||
def _test_bind_port(self, fake_segments):
|
def _test_bind_port(self, fake_segments):
|
||||||
|
fake_chassis = fakes.FakeChassis.create(datapath_type=DEFAULT_DP_TYPE)
|
||||||
|
self.sb_ovn.db_find.return_value.execute.return_value = [
|
||||||
|
{'other_config': fake_chassis.other_config}]
|
||||||
fake_port = fakes.FakePort.create_one_port().info()
|
fake_port = fakes.FakePort.create_one_port().info()
|
||||||
fake_host = 'host'
|
fake_host = 'host'
|
||||||
fake_port_context = fakes.FakePortContext(
|
fake_port_context = fakes.FakePortContext(
|
||||||
@ -1250,12 +1269,18 @@ class TestOVNMechanismDriver(TestOVNMechanismDriverBase):
|
|||||||
neutron_agent.AgentCache().get_agents.assert_called_once_with(
|
neutron_agent.AgentCache().get_agents.assert_called_once_with(
|
||||||
{'host': fake_host,
|
{'host': fake_host,
|
||||||
'agent_type': ovn_const.OVN_CONTROLLER_TYPES})
|
'agent_type': ovn_const.OVN_CONTROLLER_TYPES})
|
||||||
fake_port_context.set_binding.assert_called_once_with(
|
vif_details = copy.deepcopy(
|
||||||
fake_segments[0]['id'],
|
|
||||||
portbindings.VIF_TYPE_OVS,
|
|
||||||
self.mech_driver.vif_details[portbindings.VIF_TYPE_OVS])
|
self.mech_driver.vif_details[portbindings.VIF_TYPE_OVS])
|
||||||
|
vif_details[
|
||||||
|
portbindings.VIF_DETAILS_BRIDGE_NAME] = n_const.DEFAULT_BR_INT
|
||||||
|
vif_details[portbindings.OVS_DATAPATH_TYPE] = DEFAULT_DP_TYPE
|
||||||
|
fake_port_context.set_binding.assert_called_once_with(
|
||||||
|
fake_segments[0]['id'], portbindings.VIF_TYPE_OVS, vif_details)
|
||||||
|
|
||||||
def _test_bind_port_sriov(self, fake_segments):
|
def _test_bind_port_sriov(self, fake_segments):
|
||||||
|
fake_chassis = fakes.FakeChassis.create(datapath_type=DEFAULT_DP_TYPE)
|
||||||
|
self.sb_ovn.db_find.return_value.execute.return_value = [
|
||||||
|
{'other_config': fake_chassis.other_config}]
|
||||||
fake_port = fakes.FakePort.create_one_port(
|
fake_port = fakes.FakePort.create_one_port(
|
||||||
attrs={'binding:vnic_type': 'direct',
|
attrs={'binding:vnic_type': 'direct',
|
||||||
'binding:profile': {
|
'binding:profile': {
|
||||||
@ -1268,12 +1293,18 @@ class TestOVNMechanismDriver(TestOVNMechanismDriverBase):
|
|||||||
neutron_agent.AgentCache().get_agents.assert_called_once_with(
|
neutron_agent.AgentCache().get_agents.assert_called_once_with(
|
||||||
{'host': fake_host,
|
{'host': fake_host,
|
||||||
'agent_type': ovn_const.OVN_CONTROLLER_TYPES})
|
'agent_type': ovn_const.OVN_CONTROLLER_TYPES})
|
||||||
fake_port_context.set_binding.assert_called_once_with(
|
vif_details = copy.deepcopy(
|
||||||
fake_segments[0]['id'],
|
|
||||||
portbindings.VIF_TYPE_OVS,
|
|
||||||
self.mech_driver.vif_details[portbindings.VIF_TYPE_OVS])
|
self.mech_driver.vif_details[portbindings.VIF_TYPE_OVS])
|
||||||
|
vif_details[
|
||||||
|
portbindings.VIF_DETAILS_BRIDGE_NAME] = n_const.DEFAULT_BR_INT
|
||||||
|
vif_details[portbindings.OVS_DATAPATH_TYPE] = DEFAULT_DP_TYPE
|
||||||
|
fake_port_context.set_binding.assert_called_once_with(
|
||||||
|
fake_segments[0]['id'], portbindings.VIF_TYPE_OVS, vif_details)
|
||||||
|
|
||||||
def _test_bind_port_virtio_forwarder(self, fake_segments):
|
def _test_bind_port_virtio_forwarder(self, fake_segments):
|
||||||
|
fake_chassis = fakes.FakeChassis.create(datapath_type=DEFAULT_DP_TYPE)
|
||||||
|
self.sb_ovn.db_find.return_value.execute.return_value = [
|
||||||
|
{'other_config': fake_chassis.other_config}]
|
||||||
fake_port = fakes.FakePort.create_one_port(
|
fake_port = fakes.FakePort.create_one_port(
|
||||||
attrs={'binding:vnic_type': 'virtio-forwarder'}).info()
|
attrs={'binding:vnic_type': 'virtio-forwarder'}).info()
|
||||||
fake_host = 'host'
|
fake_host = 'host'
|
||||||
@ -1281,11 +1312,15 @@ class TestOVNMechanismDriver(TestOVNMechanismDriverBase):
|
|||||||
fake_port, fake_host, fake_segments)
|
fake_port, fake_host, fake_segments)
|
||||||
self.mech_driver.bind_port(fake_port_context)
|
self.mech_driver.bind_port(fake_port_context)
|
||||||
|
|
||||||
vif_details = self.mech_driver.\
|
vif_details = copy.deepcopy(
|
||||||
vif_details[portbindings.VIF_TYPE_AGILIO_OVS]
|
self.mech_driver.vif_details[portbindings.VIF_TYPE_AGILIO_OVS])
|
||||||
vif_details.update({"vhostuser_socket": ovn_utils.ovn_vhu_sockpath(
|
vif_details.update({
|
||||||
ovn_conf.get_ovn_vhost_sock_dir(), fake_port['id'])})
|
'vhostuser_socket': ovn_utils.ovn_vhu_sockpath(
|
||||||
vif_details.update({"vhostuser_mode": "client"})
|
ovn_conf.get_ovn_vhost_sock_dir(), fake_port['id']),
|
||||||
|
'vhostuser_mode': 'client',
|
||||||
|
portbindings.VIF_DETAILS_BRIDGE_NAME: n_const.DEFAULT_BR_INT,
|
||||||
|
portbindings.OVS_DATAPATH_TYPE: DEFAULT_DP_TYPE,
|
||||||
|
})
|
||||||
|
|
||||||
neutron_agent.AgentCache().get_agents.assert_called_once_with(
|
neutron_agent.AgentCache().get_agents.assert_called_once_with(
|
||||||
{'host': fake_host,
|
{'host': fake_host,
|
||||||
@ -1312,6 +1347,9 @@ class TestOVNMechanismDriver(TestOVNMechanismDriverBase):
|
|||||||
attrs={'hostname': fake_smartnic_dpu},
|
attrs={'hostname': fake_smartnic_dpu},
|
||||||
card_serial_number=fake_serial)
|
card_serial_number=fake_serial)
|
||||||
|
|
||||||
|
fake_chassis = fakes.FakeChassis.create(datapath_type=DEFAULT_DP_TYPE)
|
||||||
|
self.sb_ovn.db_find.return_value.execute.return_value = [
|
||||||
|
{'other_config': fake_chassis.other_config}]
|
||||||
self.sb_ovn.get_chassis_by_card_serial_from_cms_options.\
|
self.sb_ovn.get_chassis_by_card_serial_from_cms_options.\
|
||||||
return_value = ch_smartnic_dpu
|
return_value = ch_smartnic_dpu
|
||||||
fake_host = 'host'
|
fake_host = 'host'
|
||||||
@ -1321,12 +1359,18 @@ class TestOVNMechanismDriver(TestOVNMechanismDriverBase):
|
|||||||
neutron_agent.AgentCache().get_agents.assert_called_once_with(
|
neutron_agent.AgentCache().get_agents.assert_called_once_with(
|
||||||
{'host': fake_smartnic_dpu,
|
{'host': fake_smartnic_dpu,
|
||||||
'agent_type': ovn_const.OVN_CONTROLLER_TYPES})
|
'agent_type': ovn_const.OVN_CONTROLLER_TYPES})
|
||||||
fake_port_context.set_binding.assert_called_once_with(
|
vif_details = copy.deepcopy(
|
||||||
fake_segments[0]['id'],
|
|
||||||
portbindings.VIF_TYPE_OVS,
|
|
||||||
self.mech_driver.vif_details[portbindings.VIF_TYPE_OVS])
|
self.mech_driver.vif_details[portbindings.VIF_TYPE_OVS])
|
||||||
|
vif_details[
|
||||||
|
portbindings.VIF_DETAILS_BRIDGE_NAME] = n_const.DEFAULT_BR_INT
|
||||||
|
vif_details[portbindings.OVS_DATAPATH_TYPE] = DEFAULT_DP_TYPE
|
||||||
|
fake_port_context.set_binding.assert_called_once_with(
|
||||||
|
fake_segments[0]['id'], portbindings.VIF_TYPE_OVS, vif_details)
|
||||||
|
|
||||||
def test_bind_port_vdpa(self):
|
def test_bind_port_vdpa(self):
|
||||||
|
fake_chassis = fakes.FakeChassis.create(datapath_type=DEFAULT_DP_TYPE)
|
||||||
|
self.sb_ovn.db_find.return_value.execute.return_value = [
|
||||||
|
{'other_config': fake_chassis.other_config}]
|
||||||
segment_attrs = {'network_type': 'geneve',
|
segment_attrs = {'network_type': 'geneve',
|
||||||
'physical_network': None,
|
'physical_network': None,
|
||||||
'segmentation_id': 1023}
|
'segmentation_id': 1023}
|
||||||
@ -1343,10 +1387,13 @@ class TestOVNMechanismDriver(TestOVNMechanismDriverBase):
|
|||||||
neutron_agent.AgentCache().get_agents.assert_called_once_with(
|
neutron_agent.AgentCache().get_agents.assert_called_once_with(
|
||||||
{'host': fake_host,
|
{'host': fake_host,
|
||||||
'agent_type': ovn_const.OVN_CONTROLLER_TYPES})
|
'agent_type': ovn_const.OVN_CONTROLLER_TYPES})
|
||||||
fake_port_context.set_binding.assert_called_once_with(
|
vif_details = copy.deepcopy(
|
||||||
fake_segments[0]['id'],
|
|
||||||
portbindings.VIF_TYPE_OVS,
|
|
||||||
self.mech_driver.vif_details[portbindings.VIF_TYPE_OVS])
|
self.mech_driver.vif_details[portbindings.VIF_TYPE_OVS])
|
||||||
|
vif_details[
|
||||||
|
portbindings.VIF_DETAILS_BRIDGE_NAME] = n_const.DEFAULT_BR_INT
|
||||||
|
vif_details[portbindings.OVS_DATAPATH_TYPE] = DEFAULT_DP_TYPE
|
||||||
|
fake_port_context.set_binding.assert_called_once_with(
|
||||||
|
fake_segments[0]['id'], portbindings.VIF_TYPE_OVS, vif_details)
|
||||||
|
|
||||||
def test_bind_port_geneve(self):
|
def test_bind_port_geneve(self):
|
||||||
segment_attrs = {'network_type': 'geneve',
|
segment_attrs = {'network_type': 'geneve',
|
||||||
@ -2374,7 +2421,7 @@ class TestOVNMechanismDriver(TestOVNMechanismDriverBase):
|
|||||||
mock_notify_dhcp.assert_called_with(fake_port['id'])
|
mock_notify_dhcp.assert_called_with(fake_port['id'])
|
||||||
|
|
||||||
def test_agent_alive_true(self):
|
def test_agent_alive_true(self):
|
||||||
chassis_private = self._add_chassis(5)
|
chassis_private = self._add_chassis_private(5)
|
||||||
for agent_type in (ovn_const.OVN_CONTROLLER_AGENT,
|
for agent_type in (ovn_const.OVN_CONTROLLER_AGENT,
|
||||||
ovn_const.OVN_METADATA_AGENT):
|
ovn_const.OVN_METADATA_AGENT):
|
||||||
self.mech_driver.nb_ovn.nb_global.nb_cfg = 5
|
self.mech_driver.nb_ovn.nb_global.nb_cfg = 5
|
||||||
@ -2386,7 +2433,7 @@ class TestOVNMechanismDriver(TestOVNMechanismDriverBase):
|
|||||||
# Agent should be reported as alive when the nb_cfg delta is 1
|
# Agent should be reported as alive when the nb_cfg delta is 1
|
||||||
# even if the last update time was old enough.
|
# even if the last update time was old enough.
|
||||||
nb_cfg = 5
|
nb_cfg = 5
|
||||||
chassis_private = self._add_chassis(nb_cfg)
|
chassis_private = self._add_chassis_private(nb_cfg)
|
||||||
for agent_type in (ovn_const.OVN_CONTROLLER_AGENT,
|
for agent_type in (ovn_const.OVN_CONTROLLER_AGENT,
|
||||||
ovn_const.OVN_METADATA_AGENT):
|
ovn_const.OVN_METADATA_AGENT):
|
||||||
self.mech_driver.nb_ovn.nb_global.nb_cfg = nb_cfg + 1
|
self.mech_driver.nb_ovn.nb_global.nb_cfg = nb_cfg + 1
|
||||||
@ -2401,7 +2448,7 @@ class TestOVNMechanismDriver(TestOVNMechanismDriverBase):
|
|||||||
|
|
||||||
def test_agent_alive_not_timed_out(self):
|
def test_agent_alive_not_timed_out(self):
|
||||||
nb_cfg = 3
|
nb_cfg = 3
|
||||||
chassis_private = self._add_chassis(nb_cfg)
|
chassis_private = self._add_chassis_private(nb_cfg)
|
||||||
for agent_type in (ovn_const.OVN_CONTROLLER_AGENT,
|
for agent_type in (ovn_const.OVN_CONTROLLER_AGENT,
|
||||||
ovn_const.OVN_METADATA_AGENT):
|
ovn_const.OVN_METADATA_AGENT):
|
||||||
self.mech_driver.nb_ovn.nb_global.nb_cfg = nb_cfg + 2
|
self.mech_driver.nb_ovn.nb_global.nb_cfg = nb_cfg + 2
|
||||||
@ -2412,7 +2459,7 @@ class TestOVNMechanismDriver(TestOVNMechanismDriverBase):
|
|||||||
|
|
||||||
def test_agent_alive_timed_out(self):
|
def test_agent_alive_timed_out(self):
|
||||||
nb_cfg = 3
|
nb_cfg = 3
|
||||||
chassis_private = self._add_chassis(nb_cfg)
|
chassis_private = self._add_chassis_private(nb_cfg)
|
||||||
for agent_type in (ovn_const.OVN_CONTROLLER_AGENT,
|
for agent_type in (ovn_const.OVN_CONTROLLER_AGENT,
|
||||||
ovn_const.OVN_METADATA_AGENT):
|
ovn_const.OVN_METADATA_AGENT):
|
||||||
self.mech_driver.nb_ovn.nb_global.nb_cfg = nb_cfg + 2
|
self.mech_driver.nb_ovn.nb_global.nb_cfg = nb_cfg + 2
|
||||||
@ -2427,7 +2474,7 @@ class TestOVNMechanismDriver(TestOVNMechanismDriverBase):
|
|||||||
|
|
||||||
def test_agent_with_nb_cfg_timestamp_timeout(self):
|
def test_agent_with_nb_cfg_timestamp_timeout(self):
|
||||||
nb_cfg = 3
|
nb_cfg = 3
|
||||||
chassis_private = self._add_chassis(nb_cfg)
|
chassis_private = self._add_chassis_private(nb_cfg)
|
||||||
|
|
||||||
self.mech_driver.nb_ovn.nb_global.nb_cfg = nb_cfg + 2
|
self.mech_driver.nb_ovn.nb_global.nb_cfg = nb_cfg + 2
|
||||||
updated_at = (timeutils.utcnow_ts() - cfg.CONF.agent_down_time - 1
|
updated_at = (timeutils.utcnow_ts() - cfg.CONF.agent_down_time - 1
|
||||||
@ -2441,7 +2488,7 @@ class TestOVNMechanismDriver(TestOVNMechanismDriverBase):
|
|||||||
|
|
||||||
def test_agent_with_nb_cfg_timestamp_not_timeout(self):
|
def test_agent_with_nb_cfg_timestamp_not_timeout(self):
|
||||||
nb_cfg = 3
|
nb_cfg = 3
|
||||||
chassis_private = self._add_chassis(nb_cfg)
|
chassis_private = self._add_chassis_private(nb_cfg)
|
||||||
|
|
||||||
self.mech_driver.nb_ovn.nb_global.nb_cfg = nb_cfg + 2
|
self.mech_driver.nb_ovn.nb_global.nb_cfg = nb_cfg + 2
|
||||||
updated_at = timeutils.utcnow_ts() * 1000
|
updated_at = timeutils.utcnow_ts() * 1000
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
import copy
|
||||||
from unittest import mock
|
from unittest import mock
|
||||||
|
|
||||||
from neutron_lib.api.definitions import portbindings as pb
|
from neutron_lib.api.definitions import portbindings as pb
|
||||||
@ -21,6 +21,7 @@ from neutron_lib.db import api as db_api
|
|||||||
from neutron_lib import exceptions
|
from neutron_lib import exceptions
|
||||||
from oslo_utils import uuidutils
|
from oslo_utils import uuidutils
|
||||||
|
|
||||||
|
from neutron.common import _constants as n_const
|
||||||
from neutron.db.models.plugins.ml2 import geneveallocation
|
from neutron.db.models.plugins.ml2 import geneveallocation
|
||||||
from neutron.db.models.plugins.ml2 import vxlanallocation
|
from neutron.db.models.plugins.ml2 import vxlanallocation
|
||||||
from neutron.objects import ports as port_obj
|
from neutron.objects import ports as port_obj
|
||||||
@ -48,6 +49,7 @@ class TestMigrateNeutronDatabaseToOvn(
|
|||||||
|
|
||||||
for vif_details in vif_details_list:
|
for vif_details in vif_details_list:
|
||||||
port = self._make_port(self.fmt, network_id)['port']
|
port = self._make_port(self.fmt, network_id)['port']
|
||||||
|
with db_api.CONTEXT_WRITER.using(ctx):
|
||||||
port_o = port_obj.PortBinding.get_object(
|
port_o = port_obj.PortBinding.get_object(
|
||||||
ctx, port_id=port['id'], host='')
|
ctx, port_id=port['id'], host='')
|
||||||
port_o.vif_type = 'ovs'
|
port_o.vif_type = 'ovs'
|
||||||
@ -152,14 +154,10 @@ class TestMigrateNeutronDatabaseToOvn(
|
|||||||
{"foo": "bar"},
|
{"foo": "bar"},
|
||||||
{},
|
{},
|
||||||
]
|
]
|
||||||
expected_vif_details = [
|
expected_vif_details = copy.deepcopy(vif_details_list)
|
||||||
{pb.CAP_PORT_FILTER: "true",
|
for vif_detail in expected_vif_details:
|
||||||
pb.OVS_HYBRID_PLUG: "true",
|
vif_detail[pb.VIF_DETAILS_BRIDGE_NAME] = n_const.DEFAULT_BR_INT
|
||||||
pb.VIF_DETAILS_CONNECTIVITY: pb.CONNECTIVITY_L2},
|
expected_vif_details.append({})
|
||||||
{pb.CAP_PORT_FILTER: "true"},
|
|
||||||
{"foo": "bar"},
|
|
||||||
{},
|
|
||||||
]
|
|
||||||
|
|
||||||
self._create_ml2_ovs_test_resources(vif_details_list)
|
self._create_ml2_ovs_test_resources(vif_details_list)
|
||||||
db_migration.migrate_neutron_database_to_ovn()
|
db_migration.migrate_neutron_database_to_ovn()
|
||||||
|
@ -0,0 +1,8 @@
|
|||||||
|
---
|
||||||
|
fixes:
|
||||||
|
- |
|
||||||
|
[`bug 2045889 <https://bugs.launchpad.net/neutron/+bug/2045889>`_]
|
||||||
|
The ports bound to ML2/OVN now contain the OVS bridge name and datapath
|
||||||
|
type in the VIF details dictionary. NOTE: in the ML2/OVS to ML2/OVN
|
||||||
|
migration, the local host OVN bridge (integration bridge) per port is not
|
||||||
|
known; "br-int" will be used by default (that value is rarely changed).
|
Loading…
Reference in New Issue
Block a user