Update tap ip in metadata agent when metadata port ip updated
Update neutron-ovn-metadata-agent, catch port_binding update event of monitoring localport type, and judge if the neutron:cidrs field in the external_ids of port_binding table has changed, then update_datapath. Closes-Bug: #1996677 Change-Id: Ibdc1b385b07a2ab1ca8e4b6278f6d39fb5839509
This commit is contained in:
parent
a358bb802b
commit
686698284b
@ -43,7 +43,7 @@ CHASSIS_METADATA_LOCK = 'chassis_metadata_lock'
|
|||||||
|
|
||||||
NS_PREFIX = 'ovnmeta-'
|
NS_PREFIX = 'ovnmeta-'
|
||||||
MAC_PATTERN = re.compile(r'([0-9A-F]{2}[:-]){5}([0-9A-F]{2})', re.I)
|
MAC_PATTERN = re.compile(r'([0-9A-F]{2}[:-]){5}([0-9A-F]{2})', re.I)
|
||||||
OVN_VIF_PORT_TYPES = ("", "external", )
|
OVN_VIF_PORT_TYPES = ("", "external", ovn_const.LSP_TYPE_LOCALPORT, )
|
||||||
|
|
||||||
MetadataPortInfo = collections.namedtuple('MetadataPortInfo', ['mac',
|
MetadataPortInfo = collections.namedtuple('MetadataPortInfo', ['mac',
|
||||||
'ip_addresses'])
|
'ip_addresses'])
|
||||||
@ -82,6 +82,20 @@ class PortBindingChassisEvent(row_event.RowEvent):
|
|||||||
resync = False
|
resync = False
|
||||||
if row.type not in OVN_VIF_PORT_TYPES:
|
if row.type not in OVN_VIF_PORT_TYPES:
|
||||||
return
|
return
|
||||||
|
if row.type == ovn_const.LSP_TYPE_LOCALPORT:
|
||||||
|
new_ext_ids = row.external_ids
|
||||||
|
old_ext_ids = old.external_ids
|
||||||
|
device_id = row.external_ids.get(
|
||||||
|
ovn_const.OVN_DEVID_EXT_ID_KEY, "")
|
||||||
|
if not device_id.startswith(NS_PREFIX):
|
||||||
|
return
|
||||||
|
new_cidrs = new_ext_ids.get(ovn_const.OVN_CIDRS_EXT_ID_KEY, "")
|
||||||
|
old_cidrs = old_ext_ids.get(ovn_const.OVN_CIDRS_EXT_ID_KEY, "")
|
||||||
|
# If old_cidrs is "", it is create event,
|
||||||
|
# nothing needs to be done.
|
||||||
|
# If old_cidrs equals new_cidrs, the ip does not change.
|
||||||
|
if old_cidrs in ("", new_cidrs, ):
|
||||||
|
return
|
||||||
with _SYNC_STATE_LOCK.read_lock():
|
with _SYNC_STATE_LOCK.read_lock():
|
||||||
try:
|
try:
|
||||||
net_name = ovn_utils.get_network_name_from_datapath(
|
net_name = ovn_utils.get_network_name_from_datapath(
|
||||||
@ -96,6 +110,24 @@ class PortBindingChassisEvent(row_event.RowEvent):
|
|||||||
self.agent.resync()
|
self.agent.resync()
|
||||||
|
|
||||||
|
|
||||||
|
class PortBindingMetaPortUpdatedEvent(PortBindingChassisEvent):
|
||||||
|
LOG_MSG = "Metadata Port %s in datapath %s updated."
|
||||||
|
|
||||||
|
def __init__(self, metadata_agent):
|
||||||
|
events = (self.ROW_UPDATE,)
|
||||||
|
super(PortBindingMetaPortUpdatedEvent, self).__init__(
|
||||||
|
metadata_agent, events)
|
||||||
|
|
||||||
|
def match_fn(self, event, row, old):
|
||||||
|
if row.type == ovn_const.LSP_TYPE_LOCALPORT:
|
||||||
|
if hasattr(row, 'external_ids') and hasattr(old, 'external_ids'):
|
||||||
|
device_id = row.external_ids.get(
|
||||||
|
ovn_const.OVN_DEVID_EXT_ID_KEY, "")
|
||||||
|
if device_id.startswith(NS_PREFIX):
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
class PortBindingChassisCreatedEvent(PortBindingChassisEvent):
|
class PortBindingChassisCreatedEvent(PortBindingChassisEvent):
|
||||||
LOG_MSG = "Port %s in datapath %s bound to our chassis"
|
LOG_MSG = "Port %s in datapath %s bound to our chassis"
|
||||||
|
|
||||||
@ -245,7 +277,8 @@ class MetadataAgent(object):
|
|||||||
'Chassis')
|
'Chassis')
|
||||||
events = (PortBindingChassisCreatedEvent(self),
|
events = (PortBindingChassisCreatedEvent(self),
|
||||||
PortBindingChassisDeletedEvent(self),
|
PortBindingChassisDeletedEvent(self),
|
||||||
SbGlobalUpdateEvent(self))
|
SbGlobalUpdateEvent(self),
|
||||||
|
PortBindingMetaPortUpdatedEvent(self))
|
||||||
|
|
||||||
# TODO(lucasagomes): Remove this in the future. Try to register
|
# TODO(lucasagomes): Remove this in the future. Try to register
|
||||||
# the Chassis_Private table, if not present, fallback to the normal
|
# the Chassis_Private table, if not present, fallback to the normal
|
||||||
|
@ -141,7 +141,19 @@ class TestMetadataAgent(base.TestOVNFunctionalBase):
|
|||||||
type=ovn_const.LSP_TYPE_LOCALPORT,
|
type=ovn_const.LSP_TYPE_LOCALPORT,
|
||||||
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
|
||||||
|
}))
|
||||||
|
return mdt_port_name
|
||||||
|
|
||||||
|
def _update_metadata_port_ip(self, metadata_port_name):
|
||||||
|
external_ids = {
|
||||||
|
ovn_const.OVN_CIDRS_EXT_ID_KEY: "192.168.122.2/24",
|
||||||
|
ovn_const.OVN_DEVID_EXT_ID_KEY:
|
||||||
|
'ovnmeta-' + uuidutils.generate_uuid()
|
||||||
|
}
|
||||||
|
self.nb_api.set_lswitch_port(lport_name=metadata_port_name,
|
||||||
|
external_ids=external_ids).execute()
|
||||||
|
|
||||||
def _create_logical_switch_port(self, type_=None):
|
def _create_logical_switch_port(self, type_=None):
|
||||||
lswitch_name = 'ovn-' + uuidutils.generate_uuid()
|
lswitch_name = 'ovn-' + uuidutils.generate_uuid()
|
||||||
@ -192,16 +204,25 @@ class TestMetadataAgent(base.TestOVNFunctionalBase):
|
|||||||
|
|
||||||
n_utils.wait_until_true(check_mock_pbinding, timeout=10, exception=exc)
|
n_utils.wait_until_true(check_mock_pbinding, timeout=10, exception=exc)
|
||||||
|
|
||||||
def _test_agent_events(self, delete, type_=None):
|
def _test_agent_events(self, delete, type_=None, update=False):
|
||||||
m_pb_created = mock.patch.object(
|
m_pb_created = mock.patch.object(
|
||||||
agent.PortBindingChassisCreatedEvent, 'run').start()
|
agent.PortBindingChassisCreatedEvent, 'run').start()
|
||||||
m_pb_deleted = mock.patch.object(
|
m_pb_deleted = mock.patch.object(
|
||||||
agent.PortBindingChassisDeletedEvent, 'run').start()
|
agent.PortBindingChassisDeletedEvent, 'run').start()
|
||||||
|
m_pb_updated = mock.patch.object(
|
||||||
|
agent.PortBindingMetaPortUpdatedEvent, 'run').start()
|
||||||
|
|
||||||
lswitchport_name, lswitch_name = self._create_logical_switch_port(
|
lswitchport_name, lswitch_name = self._create_logical_switch_port(
|
||||||
type_)
|
type_)
|
||||||
self.sb_api.lsp_bind(lswitchport_name, self.chassis_name).execute(
|
self.sb_api.lsp_bind(lswitchport_name, self.chassis_name).execute(
|
||||||
check_error=True, log_errors=True)
|
check_error=True, log_errors=True)
|
||||||
|
if update and type_ == ovn_const.LSP_TYPE_LOCALPORT:
|
||||||
|
with self.nb_api.transaction(
|
||||||
|
check_error=True, log_errors=True) as txn:
|
||||||
|
mdt_port_name = self._create_metadata_port(txn, lswitch_name)
|
||||||
|
self.sb_api.lsp_bind(mdt_port_name, self.chassis_name).execute(
|
||||||
|
check_error=True, log_errors=True)
|
||||||
|
self._update_metadata_port_ip(mdt_port_name)
|
||||||
|
|
||||||
def pb_created():
|
def pb_created():
|
||||||
if m_pb_created.call_count < 1:
|
if m_pb_created.call_count < 1:
|
||||||
@ -219,6 +240,31 @@ class TestMetadataAgent(base.TestOVNFunctionalBase):
|
|||||||
"PortBindingChassisCreatedEvent didn't happen on port "
|
"PortBindingChassisCreatedEvent didn't happen on port "
|
||||||
"binding."))
|
"binding."))
|
||||||
|
|
||||||
|
def pb_updated():
|
||||||
|
if m_pb_updated.call_count < 1:
|
||||||
|
return False
|
||||||
|
args = m_pb_updated.call_args[0]
|
||||||
|
self.assertEqual('update', args[0])
|
||||||
|
self.assertTrue(args[1].external_ids)
|
||||||
|
self.assertTrue(args[2].external_ids)
|
||||||
|
device_id = args[1].external_ids.get(
|
||||||
|
ovn_const.OVN_DEVID_EXT_ID_KEY, "")
|
||||||
|
self.assertTrue(device_id.startswith("ovnmeta-"))
|
||||||
|
new_cidrs = args[1].external_ids.get(
|
||||||
|
ovn_const.OVN_CIDRS_EXT_ID_KEY, "")
|
||||||
|
old_cidrs = args[2].external_ids.get(
|
||||||
|
ovn_const.OVN_CIDRS_EXT_ID_KEY, "")
|
||||||
|
self.assertNotEqual(new_cidrs, old_cidrs)
|
||||||
|
self.assertNotEqual(old_cidrs, "")
|
||||||
|
return True
|
||||||
|
if update and type_ == ovn_const.LSP_TYPE_LOCALPORT:
|
||||||
|
n_utils.wait_until_true(
|
||||||
|
pb_updated,
|
||||||
|
timeout=10,
|
||||||
|
exception=Exception(
|
||||||
|
"PortBindingMetaPortUpdatedEvent didn't happen on "
|
||||||
|
"metadata port ip address updated."))
|
||||||
|
|
||||||
if delete:
|
if delete:
|
||||||
self.nb_api.delete_lswitch_port(
|
self.nb_api.delete_lswitch_port(
|
||||||
lswitchport_name, lswitch_name).execute(
|
lswitchport_name, lswitch_name).execute(
|
||||||
@ -290,6 +336,10 @@ class TestMetadataAgent(base.TestOVNFunctionalBase):
|
|||||||
timeout=10,
|
timeout=10,
|
||||||
exception=exc)
|
exception=exc)
|
||||||
|
|
||||||
|
def test_agent_metadata_port_ip_update_event(self):
|
||||||
|
self._test_agent_events(
|
||||||
|
delete=False, type_=ovn_const.LSP_TYPE_LOCALPORT, update=True)
|
||||||
|
|
||||||
def test_metadata_agent_only_monitors_own_chassis(self):
|
def test_metadata_agent_only_monitors_own_chassis(self):
|
||||||
# We already have the fake chassis which we should be monitoring, so
|
# We already have the fake chassis which we should be monitoring, so
|
||||||
# create an event looking for a change to another chassis
|
# create an event looking for a change to another chassis
|
||||||
|
6
releasenotes/notes/bug-1996677-64851b476a0c5a37.yaml
Normal file
6
releasenotes/notes/bug-1996677-64851b476a0c5a37.yaml
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
---
|
||||||
|
fixes:
|
||||||
|
- |
|
||||||
|
`1996677 <https://bugs.launchpad.net/neutron/+bug/1996677>`_
|
||||||
|
When the fixed_ips of metadata port is modified, the ip address of
|
||||||
|
tap device in metadata agent is modified.
|
Loading…
x
Reference in New Issue
Block a user