Files
ovn-octavia-provider/ovn_octavia_provider/ovsdb/impl_idl_ovn.py
Maciej Józefczyk 000049c15d Move OVN Octavia Provider driver code to this repository
This code moves OVN Octavia provider driver from networking-ovn
(branch master) repository to this repository.

For first step lets move code and unit tests.

Previous paths in networking-ovn tree:
./networking_ovn/octavia/ovn_driver.py -> ./ovn_octavia_provider/driver.py
./networking_ovn/tests/unit/octavia/test_ovn_driver ->
   ./ovn_octavia_provider/tests/unit/test_driver.py

There are a few files taken directly from neutron
repository that could be removed when neutron-lib
including those will be released:
./ovn_octavia_provider/ovsdb/impl_idl_ovn.py
./ovn_octavia_provider/ovsdb/ovsdb_monitor.py

Co-Authored-By: Brian Haley <bhaley@redhat.com>
Co-Authored-By: Carlos Goncalves <cgoncalves@redhat.com>
Co-Authored-By: Frode Nordahl <frode.nordahl@canonical.com>
Co-Authored-By: Jakub Libosvar <libosvar@redhat.com>
Co-Authored-By: Maciej Józefczyk <mjozefcz@redhat.com>
Co-Authored-By: Numan Siddique <nusiddiq@redhat.com>
Co-Authored-By: Reedip Banerjee <rbanerje@redhat.com>
Co-Authored-By: Terry Wilson <twilson@redhat.com>
Co-Authored-By: Yunxiang Tao <taoyunxiang@cmss.chinamobile.com>
Co-Authored-By: zhufl <zhu.fanglei@zte.com.cn>

Change-Id: I9b562c4ed5f74df2c3d600356758f4648ac7770b
Related-Blueprint: neutron-ovn-merge
2020-02-18 16:23:54 +00:00

139 lines
5.2 KiB
Python

# 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.
import contextlib
from neutron_lib import exceptions as n_exc
from oslo_log import log
from ovsdbapp.backend import ovs_idl
from ovsdbapp.backend.ovs_idl import idlutils
from ovsdbapp.backend.ovs_idl import transaction as idl_trans
from ovsdbapp.schema.ovn_northbound import impl_idl as nb_impl_idl
import tenacity
from ovn_octavia_provider.common import config
from ovn_octavia_provider.common import exceptions as ovn_exc
from ovn_octavia_provider.i18n import _
LOG = log.getLogger(__name__)
class OvnNbTransaction(idl_trans.Transaction):
def __init__(self, *args, **kwargs):
# NOTE(lucasagomes): The bump_nb_cfg parameter is only used by
# the agents health status check
self.bump_nb_cfg = kwargs.pop('bump_nb_cfg', False)
super(OvnNbTransaction, self).__init__(*args, **kwargs)
def pre_commit(self, txn):
if not self.bump_nb_cfg:
return
self.api.nb_global.increment('nb_cfg')
# This version of Backend doesn't use a class variable for ovsdb_connection
# and therefor allows networking-ovn to manage connection scope on its own
class Backend(ovs_idl.Backend):
lookup_table = {}
def __init__(self, connection):
self.ovsdb_connection = connection
super(Backend, self).__init__(connection)
def start_connection(self, connection):
try:
self.ovsdb_connection.start()
except Exception as e:
connection_exception = OvsdbConnectionUnavailable(
db_schema=self.schema, error=e)
LOG.exception(connection_exception)
raise connection_exception
@property
def idl(self):
return self.ovsdb_connection.idl
@property
def tables(self):
return self.idl.tables
_tables = tables
def is_table_present(self, table_name):
return table_name in self._tables
def is_col_present(self, table_name, col_name):
return self.is_table_present(table_name) and (
col_name in self._tables[table_name].columns)
def create_transaction(self, check_error=False, log_errors=True):
return idl_trans.Transaction(
self, self.ovsdb_connection, self.ovsdb_connection.timeout,
check_error, log_errors)
# Check for a column match in the table. If not found do a retry with
# a stop delay of 10 secs. This function would be useful if the caller
# wants to verify for the presence of a particular row in the table
# with the column match before doing any transaction.
# Eg. We can check if Logical_Switch row is present before adding a
# logical switch port to it.
@tenacity.retry(retry=tenacity.retry_if_exception_type(RuntimeError),
wait=tenacity.wait_exponential(),
stop=tenacity.stop_after_delay(10),
reraise=True)
def check_for_row_by_value_and_retry(self, table, column, match):
try:
idlutils.row_by_value(self.idl, table, column, match)
except idlutils.RowNotFound:
msg = (_("%(match)s does not exist in %(column)s of %(table)s")
% {'match': match, 'column': column, 'table': table})
raise RuntimeError(msg)
class OvsdbConnectionUnavailable(n_exc.ServiceUnavailable):
message = _("OVS database connection to %(db_schema)s failed with error: "
"'%(error)s'. Verify that the OVS and OVN services are "
"available and that the 'ovn_nb_connection' and "
"'ovn_sb_connection' configuration options are correct.")
class OvsdbNbOvnIdl(nb_impl_idl.OvnNbApiIdlImpl, Backend):
def __init__(self, connection):
super(OvsdbNbOvnIdl, self).__init__(connection)
self.idl._session.reconnect.set_probe_interval(
config.get_ovn_ovsdb_probe_interval())
@property
def nb_global(self):
return next(iter(self.tables['NB_Global'].rows.values()))
def create_transaction(self, check_error=False, log_errors=True,
bump_nb_cfg=False):
return OvnNbTransaction(
self, self.ovsdb_connection, self.ovsdb_connection.timeout,
check_error, log_errors, bump_nb_cfg=bump_nb_cfg)
@contextlib.contextmanager
def transaction(self, *args, **kwargs):
"""A wrapper on the ovsdbapp transaction to work with revisions.
This method is just a wrapper around the ovsdbapp transaction
to handle revision conflicts correctly.
"""
try:
with super(OvsdbNbOvnIdl, self).transaction(*args, **kwargs) as t:
yield t
except ovn_exc.RevisionConflict as e:
LOG.info('Transaction aborted. Reason: %s', e)