Files
ovn-octavia-provider/ovn_octavia_provider/agent.py
Terry Wilson 9c2274e813 Don't create an OVSDB connection per API request
Using the default ovsdbapp.backend.ovs_idl.Backend behavior which
stores the ovsdb_connection on the Backend class itself ensures
that when Octavia does the imports necessary for instantiating the
driver, that the ovsdb_connection will remain on the class even
though the instances are deleted. This will allow us to reuse the
OVSDB connection between APIs despite octavia-api knowing nothing
about it.

In addition, __del__() can called from any thread by the garbage
collector, and so it was possible that thread.join() would be
called by the thread we were in, throwing an Exception and
preventing cleanup.

Co-authored-by: Gregory Thiemonge <gthiemon@redhat.com>
Co-authored-by: Ihar Hrachyshka <ihrachys@redhat.com>
Co-authored-by: Jakub Libosvar <jlibosva@redhat.com>

Closes-Bug: #2065460
Closes-Bug: #2065459

Change-Id: I4f5df34ab32e8b33ff54f311b9b2ac00c9be1e05
2024-05-14 18:07:13 +00:00

75 lines
2.9 KiB
Python

# Copyright 2020 Red Hat, Inc. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from oslo_log import log as logging
from ovsdbapp.backend.ovs_idl import connection
from ovn_octavia_provider.common import config as ovn_conf
from ovn_octavia_provider import event as ovn_event
from ovn_octavia_provider import helper as ovn_helper
from ovn_octavia_provider import maintenance
from ovn_octavia_provider.ovsdb import impl_idl_ovn
LOG = logging.getLogger(__name__)
OVN_EVENT_LOCK_NAME = "neutron_ovn_octavia_event_lock"
def OvnProviderAgent(exit_event):
# NOTE (froyo): Move inside class in order to avoid
# the issues on test scope colliding with Neutron
# already registered options when this register was
# called from outside of the class a soon this module
# was imported, also to cover requirement from
# OvnProviderHelper and intra references modules
ovn_conf.register_opts()
helper = ovn_helper.OvnProviderHelper()
events = [ovn_event.LogicalRouterPortEvent(helper),
ovn_event.LogicalSwitchPortUpdateEvent(helper)]
sb_events = [ovn_event.ServiceMonitorUpdateEvent(helper)]
# NOTE(mjozefcz): This API is only for handling OVSDB events!
ovn_nb_idl_for_events = impl_idl_ovn.OvnNbIdlForLb(
event_lock_name=OVN_EVENT_LOCK_NAME)
ovn_nb_idl_for_events.notify_handler.watch_events(events)
c = connection.Connection(ovn_nb_idl_for_events,
ovn_conf.get_ovn_ovsdb_timeout())
c.start()
ovn_sb_idl_for_events = impl_idl_ovn.OvnSbIdlForLb(
event_lock_name=OVN_EVENT_LOCK_NAME)
ovn_sb_idl_for_events.notify_handler.watch_events(sb_events)
ovn_sb_idl_for_events.start()
# NOTE(froyo): Maintenance task initialization added here
# as it will be a long life task managed through the Octavia
# driver agent -- unlike the OVNProviderDriver which is a
# short life service invocated by Octavia API.
maintenance_thread = maintenance.MaintenanceThread()
maintenance_thread.add_periodics(
maintenance.DBInconsistenciesPeriodics())
maintenance_thread.start()
LOG.info('OVN provider agent has started.')
exit_event.wait()
LOG.info('OVN provider agent is exiting.')
ovn_nb_idl_for_events.notify_handler.unwatch_events(events)
c.stop()
ovn_sb_idl_for_events.notify_handler.unwatch_events(sb_events)
ovn_sb_idl_for_events.stop()
maintenance_thread.stop()