Add constant to identify OVN LB HM ports
OVN metadata and OVN LB HM port (used for health checks) are both using network:distributed in the device_owner field. Some tasks in Neutron search by that value, considering just one port will exist per network with that value. This patch adds a new constant to differentiate OVN metadata ports from the OVN LB HM ones. The latter will use a device_owner of ovn-lb-hm:distributed to be different but will still receive the treatment of a localport in the OVN NB DB. Related-Bug: 2038091 Change-Id: I70de163fad34371de10fec28c51959384900ebc8
This commit is contained in:
parent
0e17bd15eb
commit
b2e14b23f3
@ -70,6 +70,10 @@ OVN_ROUTER_PORT_GW_MTU_OPTION = 'gateway_mtu'
|
|||||||
OVN_PROVNET_PORT_NAME_PREFIX = 'provnet-'
|
OVN_PROVNET_PORT_NAME_PREFIX = 'provnet-'
|
||||||
OVN_NAME_PREFIX = 'neutron-'
|
OVN_NAME_PREFIX = 'neutron-'
|
||||||
|
|
||||||
|
# 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
|
||||||
|
OVN_LB_HM_PORT_DISTRIBUTED = 'ovn-lb-hm:distributed'
|
||||||
|
|
||||||
# Agent extension constants
|
# Agent extension constants
|
||||||
OVN_AGENT_DESC_KEY = 'neutron:description'
|
OVN_AGENT_DESC_KEY = 'neutron:description'
|
||||||
OVN_AGENT_METADATA_SB_CFG_KEY = 'neutron:ovn-metadata-sb-cfg'
|
OVN_AGENT_METADATA_SB_CFG_KEY = 'neutron:ovn-metadata-sb-cfg'
|
||||||
|
@ -608,6 +608,11 @@ def is_ovn_metadata_port(port):
|
|||||||
port['device_id'].startswith('ovnmeta'))
|
port['device_id'].startswith('ovnmeta'))
|
||||||
|
|
||||||
|
|
||||||
|
def is_ovn_lb_hm_port(port):
|
||||||
|
return (port['device_owner'] == constants.OVN_LB_HM_PORT_DISTRIBUTED and
|
||||||
|
port['device_id'].startswith('ovn-lb-hm'))
|
||||||
|
|
||||||
|
|
||||||
def is_gateway_chassis_invalid(chassis_name, gw_chassis,
|
def is_gateway_chassis_invalid(chassis_name, gw_chassis,
|
||||||
physnet, chassis_physnets,
|
physnet, chassis_physnets,
|
||||||
az_hints, chassis_with_azs):
|
az_hints, chassis_with_azs):
|
||||||
|
@ -15,6 +15,7 @@ import functools
|
|||||||
import socket
|
import socket
|
||||||
import uuid
|
import uuid
|
||||||
|
|
||||||
|
from neutron_lib import constants
|
||||||
from neutron_lib import exceptions as n_exc
|
from neutron_lib import exceptions as n_exc
|
||||||
from neutron_lib.utils import helpers
|
from neutron_lib.utils import helpers
|
||||||
from oslo_log import log
|
from oslo_log import log
|
||||||
@ -929,7 +930,10 @@ class OvsdbSbOvnIdl(sb_impl_idl.OvnSbApiIdlImpl, Backend):
|
|||||||
except idlutils.RowNotFound:
|
except idlutils.RowNotFound:
|
||||||
return None
|
return None
|
||||||
cmd = self.db_find_rows('Port_Binding', ('datapath', '=', dp),
|
cmd = self.db_find_rows('Port_Binding', ('datapath', '=', dp),
|
||||||
('type', '=', ovn_const.LSP_TYPE_LOCALPORT))
|
('type', '=', ovn_const.LSP_TYPE_LOCALPORT),
|
||||||
|
('external_ids', '=', {
|
||||||
|
ovn_const.OVN_DEVICE_OWNER_EXT_ID_KEY:
|
||||||
|
constants.DEVICE_OWNER_DISTRIBUTED}))
|
||||||
return next(iter(cmd.execute(check_error=True)), None)
|
return next(iter(cmd.execute(check_error=True)), None)
|
||||||
|
|
||||||
def set_chassis_neutron_description(self, chassis, description,
|
def set_chassis_neutron_description(self, chassis, description,
|
||||||
|
@ -379,8 +379,9 @@ class OVNClient(object):
|
|||||||
cidrs += ' {}/{}'.format(ip['ip_address'],
|
cidrs += ' {}/{}'.format(ip['ip_address'],
|
||||||
subnet['cidr'].split('/')[1])
|
subnet['cidr'].split('/')[1])
|
||||||
|
|
||||||
# Metadata port.
|
# Metadata or OVN LB HM port.
|
||||||
if utils.is_ovn_metadata_port(port):
|
if (utils.is_ovn_metadata_port(port) or
|
||||||
|
utils.is_ovn_lb_hm_port(port)):
|
||||||
port_type = ovn_const.LSP_TYPE_LOCALPORT
|
port_type = ovn_const.LSP_TYPE_LOCALPORT
|
||||||
|
|
||||||
if utils.is_port_external(port):
|
if utils.is_port_external(port):
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
import re
|
import re
|
||||||
from unittest import mock
|
from unittest import mock
|
||||||
|
|
||||||
|
from neutron_lib import constants
|
||||||
from oslo_config import fixture as fixture_config
|
from oslo_config import fixture as fixture_config
|
||||||
from oslo_utils import uuidutils
|
from oslo_utils import uuidutils
|
||||||
from ovsdbapp.backend.ovs_idl import event
|
from ovsdbapp.backend.ovs_idl import event
|
||||||
@ -154,7 +155,9 @@ class TestMetadataAgent(base.TestOVNFunctionalBase):
|
|||||||
addresses='AA:AA:AA:AA:AA:AA 192.168.122.123',
|
addresses='AA:AA:AA:AA:AA:AA 192.168.122.123',
|
||||||
external_ids={
|
external_ids={
|
||||||
ovn_const.OVN_CIDRS_EXT_ID_KEY: '192.168.122.123/24',
|
ovn_const.OVN_CIDRS_EXT_ID_KEY: '192.168.122.123/24',
|
||||||
ovn_const.OVN_DEVID_EXT_ID_KEY: 'ovnmeta-' + lswitch_name
|
ovn_const.OVN_DEVID_EXT_ID_KEY: 'ovnmeta-' + lswitch_name,
|
||||||
|
ovn_const.OVN_DEVICE_OWNER_EXT_ID_KEY:
|
||||||
|
constants.DEVICE_OWNER_DISTRIBUTED
|
||||||
}))
|
}))
|
||||||
|
|
||||||
def _update_metadata_port_ip(self, metadata_port_name):
|
def _update_metadata_port_ip(self, metadata_port_name):
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
import copy
|
import copy
|
||||||
import uuid
|
import uuid
|
||||||
|
|
||||||
|
from neutron_lib import constants
|
||||||
from oslo_utils import uuidutils
|
from oslo_utils import uuidutils
|
||||||
from ovsdbapp.backend.ovs_idl import connection
|
from ovsdbapp.backend.ovs_idl import connection
|
||||||
from ovsdbapp import constants as const
|
from ovsdbapp import constants as const
|
||||||
@ -104,34 +105,62 @@ class TestSbApi(BaseOvnIdlTest):
|
|||||||
self.load_test_data()
|
self.load_test_data()
|
||||||
self.assertRaises(ValueError, self.api.get_chassis_and_physnets)
|
self.assertRaises(ValueError, self.api.get_chassis_and_physnets)
|
||||||
|
|
||||||
def _add_switch_port(self, chassis_name,
|
def _add_switch(self, chassis_name):
|
||||||
type=ovn_const.LSP_TYPE_LOCALPORT):
|
sname = utils.get_rand_device_name(prefix='switch')
|
||||||
sname, pname = (utils.get_rand_device_name(prefix=p)
|
|
||||||
for p in ('switch', 'port'))
|
|
||||||
chassis = self.api.lookup('Chassis', chassis_name)
|
chassis = self.api.lookup('Chassis', chassis_name)
|
||||||
|
with self.nbapi.transaction(check_error=True) as txn:
|
||||||
|
switch = txn.add(self.nbapi.ls_add(sname))
|
||||||
|
return chassis, switch.result
|
||||||
|
|
||||||
|
def _add_port_to_switch(
|
||||||
|
self, switch, type=ovn_const.LSP_TYPE_LOCALPORT,
|
||||||
|
device_owner=constants.DEVICE_OWNER_DISTRIBUTED):
|
||||||
|
pname = utils.get_rand_device_name(prefix='port')
|
||||||
row_event = events.WaitForCreatePortBindingEvent(pname)
|
row_event = events.WaitForCreatePortBindingEvent(pname)
|
||||||
self.handler.watch_event(row_event)
|
self.handler.watch_event(row_event)
|
||||||
with self.nbapi.transaction(check_error=True) as txn:
|
with self.nbapi.transaction(check_error=True) as txn:
|
||||||
switch = txn.add(self.nbapi.ls_add(sname))
|
port = txn.add(self.nbapi.lsp_add(
|
||||||
port = txn.add(self.nbapi.lsp_add(sname, pname, type=type))
|
switch.uuid, pname, type=type,
|
||||||
|
external_ids={
|
||||||
|
ovn_const.OVN_DEVICE_OWNER_EXT_ID_KEY: device_owner}))
|
||||||
row_event.wait()
|
row_event.wait()
|
||||||
return chassis, switch.result, port.result, row_event.row
|
return port.result, row_event.row
|
||||||
|
|
||||||
def test_get_metadata_port_network(self):
|
def test_get_metadata_port_network(self):
|
||||||
chassis, switch, port, binding = self._add_switch_port(
|
chassis, switch = self._add_switch(self.data['chassis'][0]['name'])
|
||||||
self.data['chassis'][0]['name'])
|
port, binding = self._add_port_to_switch(switch)
|
||||||
result = self.api.get_metadata_port_network(str(binding.datapath.uuid))
|
result = self.api.get_metadata_port_network(str(binding.datapath.uuid))
|
||||||
self.assertEqual(binding, result)
|
self.assertEqual(binding, result)
|
||||||
self.assertEqual(binding.datapath.external_ids['logical-switch'],
|
self.assertEqual(binding.datapath.external_ids['logical-switch'],
|
||||||
str(switch.uuid))
|
str(switch.uuid))
|
||||||
|
self.assertEqual(
|
||||||
|
port.external_ids[ovn_const.OVN_DEVICE_OWNER_EXT_ID_KEY],
|
||||||
|
constants.DEVICE_OWNER_DISTRIBUTED)
|
||||||
|
|
||||||
|
def test_get_metadata_port_network_other_non_metadata_port(self):
|
||||||
|
chassis, switch = self._add_switch(self.data['chassis'][0]['name'])
|
||||||
|
port, binding = self._add_port_to_switch(switch)
|
||||||
|
port_lbhm, binding_port_lbhm = self._add_port_to_switch(
|
||||||
|
switch, device_owner=ovn_const.OVN_LB_HM_PORT_DISTRIBUTED)
|
||||||
|
result = self.api.get_metadata_port_network(str(binding.datapath.uuid))
|
||||||
|
self.assertEqual(binding, result)
|
||||||
|
self.assertEqual(binding.datapath.external_ids['logical-switch'],
|
||||||
|
str(switch.uuid))
|
||||||
|
self.assertEqual(
|
||||||
|
binding_port_lbhm.datapath.external_ids['logical-switch'],
|
||||||
|
str(switch.uuid))
|
||||||
|
self.assertEqual(
|
||||||
|
port_lbhm.external_ids[ovn_const.OVN_DEVICE_OWNER_EXT_ID_KEY],
|
||||||
|
ovn_const.OVN_LB_HM_PORT_DISTRIBUTED)
|
||||||
|
|
||||||
def test_get_metadata_port_network_missing(self):
|
def test_get_metadata_port_network_missing(self):
|
||||||
val = str(uuid.uuid4())
|
val = str(uuid.uuid4())
|
||||||
self.assertIsNone(self.api.get_metadata_port_network(val))
|
self.assertIsNone(self.api.get_metadata_port_network(val))
|
||||||
|
|
||||||
def _create_bound_port_with_ip(self):
|
def _create_bound_port_with_ip(self):
|
||||||
chassis, switch, port, binding = self._add_switch_port(
|
chassis, switch = self._add_switch(
|
||||||
self.data['chassis'][0]['name'])
|
self.data['chassis'][0]['name'])
|
||||||
|
port, binding = self._add_port_to_switch(switch)
|
||||||
mac = 'de:ad:be:ef:4d:ad'
|
mac = 'de:ad:be:ef:4d:ad'
|
||||||
ipaddr = '192.0.2.1'
|
ipaddr = '192.0.2.1'
|
||||||
mac_ip = '%s %s' % (mac, ipaddr)
|
mac_ip = '%s %s' % (mac, ipaddr)
|
||||||
@ -165,8 +194,9 @@ class TestSbApi(BaseOvnIdlTest):
|
|||||||
self.assertEqual(1, len(result))
|
self.assertEqual(1, len(result))
|
||||||
|
|
||||||
def test_get_ports_on_chassis(self):
|
def test_get_ports_on_chassis(self):
|
||||||
chassis, switch, port, binding = self._add_switch_port(
|
chassis, switch = self._add_switch(
|
||||||
self.data['chassis'][0]['name'])
|
self.data['chassis'][0]['name'])
|
||||||
|
port, binding = self._add_port_to_switch(switch)
|
||||||
self.api.lsp_bind(port.name, chassis.name).execute(check_error=True)
|
self.api.lsp_bind(port.name, chassis.name).execute(check_error=True)
|
||||||
self.assertEqual([binding],
|
self.assertEqual([binding],
|
||||||
self.api.get_ports_on_chassis(chassis.name))
|
self.api.get_ports_on_chassis(chassis.name))
|
||||||
|
@ -217,6 +217,21 @@ class TestUtils(base.BaseTestCase):
|
|||||||
self.assertFalse(utils.is_ovn_metadata_port(non_meta_port_0))
|
self.assertFalse(utils.is_ovn_metadata_port(non_meta_port_0))
|
||||||
self.assertFalse(utils.is_ovn_metadata_port(non_meta_port_1))
|
self.assertFalse(utils.is_ovn_metadata_port(non_meta_port_1))
|
||||||
|
|
||||||
|
def test_is_ovn_lb_hm_port(self):
|
||||||
|
ovn_lb_hm_port = {
|
||||||
|
'device_owner': constants.OVN_LB_HM_PORT_DISTRIBUTED,
|
||||||
|
'device_id': 'ovn-lb-hm-12345'}
|
||||||
|
non_ovn_lb_hm_port_0 = {
|
||||||
|
'device_owner': n_const.DEVICE_OWNER_DISTRIBUTED,
|
||||||
|
'device_id': 'ovnmeta-12345'}
|
||||||
|
non_ovn_lb_hm_port_1 = {
|
||||||
|
'device_owner': n_const.DEVICE_OWNER_DHCP,
|
||||||
|
'device_id': 'dhcp-12345'}
|
||||||
|
|
||||||
|
self.assertTrue(utils.is_ovn_lb_hm_port(ovn_lb_hm_port))
|
||||||
|
self.assertFalse(utils.is_ovn_lb_hm_port(non_ovn_lb_hm_port_0))
|
||||||
|
self.assertFalse(utils.is_ovn_lb_hm_port(non_ovn_lb_hm_port_1))
|
||||||
|
|
||||||
|
|
||||||
class TestGateWayChassisValidity(base.BaseTestCase):
|
class TestGateWayChassisValidity(base.BaseTestCase):
|
||||||
|
|
||||||
|
@ -1913,6 +1913,22 @@ class TestOVNMechanismDriver(TestOVNMechanismDriverBase):
|
|||||||
self.assertEqual("address_scope_v4", options.address4_scope_id)
|
self.assertEqual("address_scope_v4", options.address4_scope_id)
|
||||||
self.assertEqual("address_scope_v6", options.address6_scope_id)
|
self.assertEqual("address_scope_v6", options.address6_scope_id)
|
||||||
|
|
||||||
|
def test__get_port_options_with_ovn_lb_hm_port(self):
|
||||||
|
port = {
|
||||||
|
'id': 'ovn-lb-hm-port',
|
||||||
|
'mac_address': '00:00:00:00:00:00',
|
||||||
|
'device_owner': ovn_const.OVN_LB_HM_PORT_DISTRIBUTED,
|
||||||
|
'device_id': 'ovn-lb-hm-foo',
|
||||||
|
'network_id': 'foo',
|
||||||
|
'fixed_ips': [],
|
||||||
|
portbindings.HOST_ID: 'fake-src',
|
||||||
|
portbindings.PROFILE: {
|
||||||
|
ovn_const.MIGRATING_ATTR: 'fake-dest',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
options = self.mech_driver._ovn_client._get_port_options(port)
|
||||||
|
self.assertEqual('fake-src', options.options['requested-chassis'])
|
||||||
|
|
||||||
def test__get_port_options_migrating_additional_chassis_missing(self):
|
def test__get_port_options_migrating_additional_chassis_missing(self):
|
||||||
port = {
|
port = {
|
||||||
'id': 'virt-port',
|
'id': 'virt-port',
|
||||||
|
@ -0,0 +1,9 @@
|
|||||||
|
---
|
||||||
|
other:
|
||||||
|
- |
|
||||||
|
The new value for 'device_owner' for OVN loadbalancer health monitor ports
|
||||||
|
(ovn-lb-hm:distributed) is now supported by Neutron, providing a LOCALPORT
|
||||||
|
behavior to these ports. The responsibility to define these ports with the
|
||||||
|
new value instead of the old one (network:distributed) is under the
|
||||||
|
OVN-Octavia Provider driver, which will take care of database conversion
|
||||||
|
for these ports.
|
Loading…
Reference in New Issue
Block a user