[OVN] The OVN agent should handle its own tags and status
The OVN agent should handle its own tags, written in the "Chassis_Private.external_ids" dictionary. These are: * neutron:ovn-neutron-agent-sb-cfg * neutron:description-neutron-agent * neutron:ovn-neutron-agent-id The "metadata" extension should not create nor update these tags. This patch removes from the "metadata" extension the ``SbGlobalUpdateEvent`` and ``ChassisPrivateCreateEvent`` events. Partial-Bug: #2119097 Signed-off-by: Rodolfo Alonso Hernandez <ralonsoh@redhat.com> Change-Id: I7f0ecf8f8727e363d98e981948c999305ae33426
This commit is contained in:
@@ -49,6 +49,32 @@ class SbGlobalUpdateEvent(row_event.RowEvent):
|
||||
('external_ids', ext_ids)).execute()
|
||||
|
||||
|
||||
class ChassisPrivateCreateEvent(row_event.RowEvent):
|
||||
"""Row create event - Chassis name == our_chassis.
|
||||
|
||||
On connection, we get a dump of all chassis so if we catch a creation
|
||||
of our own chassis it has to be a reconnection. In this case, we need
|
||||
to do a full sync to make sure that we capture all changes while the
|
||||
connection to OVSDB was down.
|
||||
"""
|
||||
def __init__(self, ovn_agent):
|
||||
self._first_time = True
|
||||
self.ovn_agent = ovn_agent
|
||||
events = (self.ROW_CREATE,)
|
||||
super().__init__(events, 'Chassis_Private', None)
|
||||
self.conditions = (('name', '=', self.ovn_agent.chassis),)
|
||||
self.event_name = self.__class__.__name__
|
||||
|
||||
def run(self, event, row, old):
|
||||
if self._first_time:
|
||||
self._first_time = False
|
||||
return
|
||||
|
||||
# Re-register the OVN agent with the local chassis in case its
|
||||
# entry was re-created (happens when restarting the ovn-controller)
|
||||
self.ovn_agent.register_ovn_agent()
|
||||
|
||||
|
||||
class OVNNeutronAgent(service.Service):
|
||||
|
||||
def __init__(self, conf):
|
||||
@@ -139,7 +165,9 @@ class OVNNeutronAgent(service.Service):
|
||||
return ovsdb.MonitorAgentOvnNbIdl(tables, events).start()
|
||||
|
||||
def _load_sb_idl(self):
|
||||
events = [SbGlobalUpdateEvent]
|
||||
events = [SbGlobalUpdateEvent,
|
||||
ChassisPrivateCreateEvent,
|
||||
]
|
||||
tables = ['SB_Global', 'Chassis_Private']
|
||||
for extension in self.ext_manager:
|
||||
events += extension.obj.sb_idl_events
|
||||
|
||||
@@ -19,6 +19,7 @@ import threading
|
||||
from neutron_lib.agent import extension
|
||||
from neutron_lib import exceptions
|
||||
from oslo_log import log as logging
|
||||
from oslo_service import service
|
||||
|
||||
from neutron._i18n import _
|
||||
from neutron.agent import agent_extensions_manager as agent_ext_mgr
|
||||
@@ -33,6 +34,35 @@ class ConfigException(exceptions.NeutronException):
|
||||
message = _('Error configuring the OVN Neutron Agent: %(description)s.')
|
||||
|
||||
|
||||
class OVNExtensionEvent(metaclass=abc.ABCMeta):
|
||||
"""Implements a method to retrieve the correct caller agent
|
||||
|
||||
The events inheriting from this class could be called from the OVN metadata
|
||||
agent or as part of an extension of the OVN agent ("metadata" extension,
|
||||
for example). In future releases, the OVN metadata agent will be superseded
|
||||
by the OVN agent (with the "metadata" extension) and this class removed,
|
||||
keeping only the compatibility with the OVN agent (to be removed in C+2).
|
||||
"""
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
self._agent_or_extension = None
|
||||
self._agent = None
|
||||
|
||||
@property
|
||||
def agent(self):
|
||||
"""This method provide support for the OVN agent
|
||||
|
||||
This event can be used in the OVN metadata agent and in the OVN
|
||||
agent metadata extension.
|
||||
"""
|
||||
if not self._agent_or_extension:
|
||||
if isinstance(self._agent, service.Service):
|
||||
self._agent_or_extension = self._agent['metadata']
|
||||
else:
|
||||
self._agent_or_extension = self._agent
|
||||
return self._agent_or_extension
|
||||
|
||||
|
||||
class OVNAgentExtensionManager(agent_ext_mgr.AgentExtensionsManager):
|
||||
|
||||
def __init__(self, conf):
|
||||
|
||||
@@ -115,8 +115,6 @@ class MetadataExtension(extension_manager.OVNAgentExtension,
|
||||
def sb_idl_events(self):
|
||||
return [metadata_agent.PortBindingUpdatedEvent,
|
||||
metadata_agent.PortBindingDeletedEvent,
|
||||
metadata_agent.SbGlobalUpdateEvent,
|
||||
metadata_agent.ChassisPrivateCreateEvent,
|
||||
]
|
||||
|
||||
# NOTE(ralonsoh): the following properties are needed during the migration
|
||||
@@ -162,7 +160,6 @@ class MetadataExtension(extension_manager.OVNAgentExtension,
|
||||
"""
|
||||
self.agent_api.load_config()
|
||||
self._update_chassis_private_config()
|
||||
self.agent_api.update_neutron_sb_cfg_key()
|
||||
self.sync()
|
||||
|
||||
def start(self):
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import abc
|
||||
import collections
|
||||
import functools
|
||||
import re
|
||||
@@ -31,7 +30,7 @@ from ovsdbapp.backend.ovs_idl import vlog
|
||||
from neutron.agent.linux import external_process
|
||||
from neutron.agent.linux import ip_lib
|
||||
from neutron.agent.linux import iptables_manager
|
||||
from neutron.agent.ovn.agent import ovn_neutron_agent
|
||||
from neutron.agent.ovn.extensions import extension_manager
|
||||
from neutron.agent.ovn.metadata import driver as metadata_driver
|
||||
from neutron.agent.ovn.metadata import ovsdb
|
||||
from neutron.agent.ovn.metadata import server_socket as metadata_server
|
||||
@@ -87,36 +86,8 @@ class ConfigException(Exception):
|
||||
"""
|
||||
|
||||
|
||||
class _OVNExtensionEvent(metaclass=abc.ABCMeta):
|
||||
"""Implements a method to retrieve the correct caller agent
|
||||
|
||||
The events inheriting from this class could be called from the OVN metadata
|
||||
agent or as part of an extension of the OVN agent ("metadata" extension,
|
||||
for example). In future releases, the OVN metadata agent will be superseded
|
||||
by the OVN agent (with the "metadata" extension) and this class removed,
|
||||
keeping only the compatibility with the OVN agent (to be removed in C+2).
|
||||
"""
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
self._agent_or_extension = None
|
||||
self._agent = None
|
||||
|
||||
@property
|
||||
def agent(self):
|
||||
"""This method provide support for the OVN agent
|
||||
|
||||
This event can be used in the OVN metadata agent and in the OVN
|
||||
agent metadata extension.
|
||||
"""
|
||||
if not self._agent_or_extension:
|
||||
if isinstance(self._agent, ovn_neutron_agent.OVNNeutronAgent):
|
||||
self._agent_or_extension = self._agent['metadata']
|
||||
else:
|
||||
self._agent_or_extension = self._agent
|
||||
return self._agent_or_extension
|
||||
|
||||
|
||||
class PortBindingEvent(_OVNExtensionEvent, row_event.RowEvent):
|
||||
class PortBindingEvent(extension_manager.OVNExtensionEvent,
|
||||
row_event.RowEvent):
|
||||
def __init__(self, agent):
|
||||
table = 'Port_Binding'
|
||||
super().__init__((self.__class__.EVENT,), table, None)
|
||||
@@ -301,7 +272,7 @@ class PortBindingDeletedEvent(PortBindingEvent):
|
||||
return True
|
||||
|
||||
|
||||
class ChassisPrivateCreateEvent(_OVNExtensionEvent, row_event.RowEvent):
|
||||
class ChassisPrivateCreateEvent(row_event.RowEvent):
|
||||
"""Row create event - Chassis name == our_chassis.
|
||||
|
||||
On connection, we get a dump of all chassis so if we catch a creation
|
||||
@@ -314,9 +285,7 @@ class ChassisPrivateCreateEvent(_OVNExtensionEvent, row_event.RowEvent):
|
||||
self.first_time = True
|
||||
events = (self.ROW_CREATE,)
|
||||
super().__init__(events, 'Chassis_Private', None)
|
||||
# NOTE(ralonsoh): ``self._agent`` needs to be assigned before being
|
||||
# used in the property ``self.agent``.
|
||||
self._agent = agent
|
||||
self.agent = agent
|
||||
self.conditions = (('name', '=', self.agent.chassis),)
|
||||
self.event_name = self.__class__.__name__
|
||||
|
||||
@@ -332,14 +301,14 @@ class ChassisPrivateCreateEvent(_OVNExtensionEvent, row_event.RowEvent):
|
||||
self.agent.sync()
|
||||
|
||||
|
||||
class SbGlobalUpdateEvent(_OVNExtensionEvent, row_event.RowEvent):
|
||||
class SbGlobalUpdateEvent(row_event.RowEvent):
|
||||
"""Row update event on SB_Global table."""
|
||||
|
||||
def __init__(self, agent):
|
||||
table = 'SB_Global'
|
||||
events = (self.ROW_UPDATE,)
|
||||
super().__init__(events, table, None)
|
||||
self._agent = agent
|
||||
self.agent = agent
|
||||
self.event_name = self.__class__.__name__
|
||||
self.first_run = True
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ import uuid
|
||||
|
||||
from oslo_config import fixture as fixture_config
|
||||
from oslo_utils import uuidutils
|
||||
from ovsdbapp.backend.ovs_idl import idlutils
|
||||
|
||||
from neutron.agent.ovn.agent import ovn_neutron_agent
|
||||
from neutron.agent.ovn.agent import ovsdb as agent_ovsdb
|
||||
@@ -94,6 +95,29 @@ class TestOVNNeutronAgentBase(base.TestOVNFunctionalBase):
|
||||
return agt
|
||||
|
||||
|
||||
class TestOVNNeutronAgent(TestOVNNeutronAgentBase):
|
||||
def setUp(self, **kwargs):
|
||||
super().setUp(extensions=[METADATA_EXTENSION], **kwargs)
|
||||
|
||||
def test_chassis_private_create_event(self):
|
||||
def _check_chassis_private():
|
||||
try:
|
||||
ext_ids = self.ovn_agent.sb_idl.db_get(
|
||||
'Chassis_Private', self.chassis_name,
|
||||
'external_ids').execute(check_error=True)
|
||||
return (ext_ids.get(ovn_const.OVN_AGENT_NEUTRON_ID_KEY)
|
||||
is not None)
|
||||
except idlutils.RowNotFound:
|
||||
return False
|
||||
|
||||
# If the "Chassis_Private" register is deleted and created again,
|
||||
# the agent should be able to re-register itself.
|
||||
self.ovn_agent.sb_idl.chassis_del(self.chassis_name).execute(
|
||||
check_error=True)
|
||||
self.add_fake_chassis(self.host_name, name=self.chassis_name)
|
||||
n_utils.wait_until_true(_check_chassis_private, timeout=10)
|
||||
|
||||
|
||||
class TestOVNNeutronAgentFakeAgent(TestOVNNeutronAgentBase):
|
||||
|
||||
def setUp(self, **kwargs):
|
||||
|
||||
Reference in New Issue
Block a user