Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package python-ovsdbapp for openSUSE:Factory 
checked in at 2023-06-22 23:25:03
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-ovsdbapp (Old)
 and      /work/SRC/openSUSE:Factory/.python-ovsdbapp.new.15902 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-ovsdbapp"

Thu Jun 22 23:25:03 2023 rev:14 rq:1093366 version:2.3.0

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-ovsdbapp/python-ovsdbapp.changes  
2023-03-07 16:50:13.125548076 +0100
+++ 
/work/SRC/openSUSE:Factory/.python-ovsdbapp.new.15902/python-ovsdbapp.changes   
    2023-06-22 23:25:13.929623435 +0200
@@ -1,0 +2,14 @@
+Thu Jun 15 20:21:45 UTC 2023 - [email protected]
+
+- update to version 2.3.0
+  - [CI] Set the default OS_TEST_PATH in the stestr conf file
+  - Use OVN's OVS submodule for functional tests
+  - Add Interface paramteres to ``OvsdbIdl.add_port`` method.
+  - All ``AddCommand`` child classes return the new register UUID
+  - Update master for stable/2023.1
+  - Add support for manipulating BFD entries
+  - Add new function ls_get_localnet_ports
+  - Add 'no timeout' option to wait_for_change
+  - Add if_exists and **kwargs columns to db_set
+
+-------------------------------------------------------------------

Old:
----
  ovsdbapp-2.2.1.tar.gz

New:
----
  ovsdbapp-2.3.0.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-ovsdbapp.spec ++++++
--- /var/tmp/diff_new_pack.csbqFT/_old  2023-06-22 23:25:14.625621668 +0200
+++ /var/tmp/diff_new_pack.csbqFT/_new  2023-06-22 23:25:14.629621659 +0200
@@ -18,13 +18,13 @@
 
 %define with_tests 1
 Name:           python-ovsdbapp
-Version:        2.2.1
+Version:        2.3.0
 Release:        0
 Summary:        A library for creating OVSDB applications
 License:        Apache-2.0
 Group:          Development/Languages/Python
 URL:            https://docs.openstack.org/ovsdbapp
-Source0:        
https://files.pythonhosted.org/packages/source/o/ovsdbapp/ovsdbapp-2.2.1.tar.gz
+Source0:        
https://files.pythonhosted.org/packages/source/o/ovsdbapp/ovsdbapp-2.3.0.tar.gz
 BuildRequires:  openstack-macros
 BuildRequires:  python3-fixtures >= 3.0.0
 BuildRequires:  python3-netaddr >= 0.7.18
@@ -70,7 +70,7 @@
 %{py3_build}
 
 # generate html docs
-PBR_VERSION=2.2.1 PYTHONPATH=. \
+PBR_VERSION=2.3.0 PYTHONPATH=. \
     %sphinx_build -b html doc/source doc/build/html
 rm -rf doc/build/html/.{doctrees,buildinfo}
 

++++++ ovsdbapp-2.2.1.tar.gz -> ovsdbapp-2.3.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ovsdbapp-2.2.1/.stestr.conf 
new/ovsdbapp-2.3.0/.stestr.conf
--- old/ovsdbapp-2.2.1/.stestr.conf     2023-02-10 17:02:24.000000000 +0100
+++ new/ovsdbapp-2.3.0/.stestr.conf     2023-04-27 17:14:09.000000000 +0200
@@ -1,4 +1,4 @@
 [DEFAULT]
-test_path=${OS_TEST_PATH}
+test_path=${OS_TEST_PATH:-./ovsdbapp/tests/unit}
 top_dir=./
 group_regex=([^\.]+\.)+
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ovsdbapp-2.2.1/AUTHORS new/ovsdbapp-2.3.0/AUTHORS
--- old/ovsdbapp-2.2.1/AUTHORS  2023-02-10 17:02:53.000000000 +0100
+++ new/ovsdbapp-2.3.0/AUTHORS  2023-04-27 17:14:39.000000000 +0200
@@ -26,6 +26,7 @@
 Emma Foley <[email protected]>
 Flavio Fernandes <[email protected]>
 Frank Wang <[email protected]>
+Frode Nordahl <[email protected]>
 Gal Sagie <[email protected]>
 Gary Kotton <[email protected]>
 Ghanshyam Mann <[email protected]>
@@ -42,6 +43,7 @@
 Jakub Libosvar <[email protected]>
 Kevin Benton <[email protected]>
 Lucas Alvares Gomes <[email protected]>
+Luis Tomas Bolivar <[email protected]>
 Luong Anh Tuan <[email protected]>
 Maciej Józefczyk <[email protected]>
 Marcin Mirecki <[email protected]>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ovsdbapp-2.2.1/ChangeLog new/ovsdbapp-2.3.0/ChangeLog
--- old/ovsdbapp-2.2.1/ChangeLog        2023-02-10 17:02:53.000000000 +0100
+++ new/ovsdbapp-2.3.0/ChangeLog        2023-04-27 17:14:39.000000000 +0200
@@ -1,6 +1,19 @@
 CHANGES
 =======
 
+2.3.0
+-----
+
+* Add support for manipulating BFD entries
+* Add if\_exists and \*\*kwargs columns to db\_set
+* Add 'no timeout' option to wait\_for\_change
+* Add Interface paramteres to \`\`OvsdbIdl.add\_port\`\` method
+* Add new function ls\_get\_localnet\_ports
+* Use OVN's OVS submodule for functional tests
+* [CI] Set the default OS\_TEST\_PATH in the stestr conf file
+* Update master for stable/2023.1
+* All \`\`AddCommand\`\` child classes return the new register UUID
+
 2.2.1
 -----
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ovsdbapp-2.2.1/PKG-INFO new/ovsdbapp-2.3.0/PKG-INFO
--- old/ovsdbapp-2.2.1/PKG-INFO 2023-02-10 17:02:54.134330700 +0100
+++ new/ovsdbapp-2.3.0/PKG-INFO 2023-04-27 17:14:39.963996200 +0200
@@ -1,6 +1,6 @@
 Metadata-Version: 1.2
 Name: ovsdbapp
-Version: 2.2.1
+Version: 2.3.0
 Summary: A library for creating OVSDB applications
 Home-page: https://pypi.org/project/ovsdbapp/
 Author: OpenStack
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ovsdbapp-2.2.1/ovsdbapp/api.py 
new/ovsdbapp-2.3.0/ovsdbapp/api.py
--- old/ovsdbapp-2.2.1/ovsdbapp/api.py  2023-02-10 17:02:24.000000000 +0100
+++ new/ovsdbapp-2.3.0/ovsdbapp/api.py  2023-04-27 17:14:09.000000000 +0200
@@ -152,7 +152,7 @@
         """
 
     @abc.abstractmethod
-    def db_set(self, table, record, *col_values):
+    def db_set(self, table, record, *col_values, if_exists=True, **columns):
         """Create a command to set fields in a record
 
         :param table:      The OVS table containing the record to be modified
@@ -162,11 +162,14 @@
         :param col_values: The columns and their associated values
         :type col_values:  Tuples of (column, value). Values may be atomic
                            values or unnested sequences/mappings
+        :param if_exists:  Do not fail if record does not exist
+        :type if_exists:   bool
+        :param columns:    The columns and their associated values
+                           (mutually exclusive with col_values and col_values
+                           is used if available)
+        :type columns:     Dictionary of columns names and values
         :returns:          :class:`Command` with no result
         """
-        # TODO(twilson) Consider handling kwargs for arguments where order
-        # doesn't matter. Though that would break the assert_called_once_with
-        # unit tests
 
     @abc.abstractmethod
     def db_add(self, table, record, column, *values):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ovsdbapp-2.2.1/ovsdbapp/backend/ovs_idl/__init__.py 
new/ovsdbapp-2.3.0/ovsdbapp/backend/ovs_idl/__init__.py
--- old/ovsdbapp-2.2.1/ovsdbapp/backend/ovs_idl/__init__.py     2023-02-10 
17:02:24.000000000 +0100
+++ new/ovsdbapp-2.3.0/ovsdbapp/backend/ovs_idl/__init__.py     2023-04-27 
17:14:09.000000000 +0200
@@ -144,8 +144,9 @@
     def db_destroy(self, table, record):
         return cmd.DbDestroyCommand(self, table, record)
 
-    def db_set(self, table, record, *col_values):
-        return cmd.DbSetCommand(self, table, record, *col_values)
+    def db_set(self, table, record, *col_values, if_exists=True, **columns):
+        return cmd.DbSetCommand(self, table, record, *col_values,
+                                if_exists=if_exists, **columns)
 
     def db_add(self, table, record, column, *values):
         return cmd.DbAddCommand(self, table, record, column, *values)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ovsdbapp-2.2.1/ovsdbapp/backend/ovs_idl/command.py 
new/ovsdbapp-2.3.0/ovsdbapp/backend/ovs_idl/command.py
--- old/ovsdbapp-2.2.1/ovsdbapp/backend/ovs_idl/command.py      2023-02-10 
17:02:24.000000000 +0100
+++ new/ovsdbapp-2.3.0/ovsdbapp/backend/ovs_idl/command.py      2023-04-27 
17:14:09.000000000 +0200
@@ -137,14 +137,22 @@
 
 
 class DbSetCommand(BaseCommand):
-    def __init__(self, api, table, record, *col_values):
+    def __init__(self, api, table, record, *col_values, if_exists=False,
+                 **columns):
         super().__init__(api)
         self.table = table
         self.record = record
-        self.col_values = col_values
+        self.col_values = col_values or columns.items()
+        self.if_exists = if_exists
 
     def run_idl(self, txn):
-        record = self.api.lookup(self.table, self.record)
+        try:
+            record = self.api.lookup(self.table, self.record)
+        except idlutils.RowNotFound:
+            if self.if_exists:
+                return
+            raise
+
         for col, val in self.col_values:
             if isinstance(val, abc.Mapping):
                 # TODO(twilson) This is to make a unit/functional test that
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ovsdbapp-2.2.1/ovsdbapp/backend/ovs_idl/idlutils.py 
new/ovsdbapp-2.3.0/ovsdbapp/backend/ovs_idl/idlutils.py
--- old/ovsdbapp-2.2.1/ovsdbapp/backend/ovs_idl/idlutils.py     2023-02-10 
17:02:24.000000000 +0100
+++ new/ovsdbapp-2.3.0/ovsdbapp/backend/ovs_idl/idlutils.py     2023-04-27 
17:14:09.000000000 +0200
@@ -231,17 +231,27 @@
     return [c.strip() for c in connection_string.split(',')]
 
 
-def wait_for_change(_idl, timeout, seqno=None):
+def wait_for_change(_idl, timeout=None, seqno=None):
+    """Wait for the Idl seqno to change
+
+    :param _idl: The Idl instance
+    :type _idl: ovs.db.idl.Idl
+    :param timeout: raise a TimeoutException after if timeout > 0/not None
+    :type timeout: int (seconds) or None
+    """
+    if timeout and timeout <= 0:
+        timeout = None
     if seqno is None:
         seqno = _idl.change_seqno
-    stop = time.time() + timeout
+    stop = time.time() + timeout if timeout else None
     while _idl.change_seqno == seqno and not _idl.run():
         ovs_poller = poller.Poller()
         _idl.wait(ovs_poller)
-        ovs_poller.timer_wait(timeout * 1000)
+        if timeout:
+            ovs_poller.timer_wait(timeout * 1000)
         ovs_poller.block()
-        if time.time() > stop:
-            raise Exception("Timeout")  # TODO(twilson) use TimeoutException?
+        if stop and time.time() >= stop:
+            raise exceptions.TimeoutException()
 
 
 def get_column_value(row, col):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ovsdbapp-2.2.1/ovsdbapp/constants.py 
new/ovsdbapp-2.3.0/ovsdbapp/constants.py
--- old/ovsdbapp-2.2.1/ovsdbapp/constants.py    2023-02-10 17:02:24.000000000 
+0100
+++ new/ovsdbapp-2.3.0/ovsdbapp/constants.py    2023-04-27 17:14:09.000000000 
+0200
@@ -39,3 +39,5 @@
 PROTO_UDP = 'udp'
 
 ROUTE_DISCARD = "discard"
+
+LOCALNET = 'localnet'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ovsdbapp-2.2.1/ovsdbapp/schema/open_vswitch/api.py 
new/ovsdbapp-2.3.0/ovsdbapp/schema/open_vswitch/api.py
--- old/ovsdbapp-2.2.1/ovsdbapp/schema/open_vswitch/api.py      2023-02-10 
17:02:24.000000000 +0100
+++ new/ovsdbapp-2.3.0/ovsdbapp/schema/open_vswitch/api.py      2023-04-27 
17:14:09.000000000 +0200
@@ -171,7 +171,7 @@
         """
 
     @abc.abstractmethod
-    def add_port(self, bridge, port, may_exist=True):
+    def add_port(self, bridge, port, may_exist=True, **interface_attrs):
         """Create a command to add a port to an OVS bridge
 
         :param bridge:    The name of the bridge
@@ -180,6 +180,9 @@
         :type port:       string
         :param may_exist: Do not fail if the port already exists
         :type may_exist:  bool
+        :param interface_attrs: Additional parameters to be set in the
+                          "Interface" register (not the "Port" register) that
+                          is created along with the "Port" one
         :returns:         :class:`Command` with RowView result
         """
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/ovsdbapp-2.2.1/ovsdbapp/schema/open_vswitch/commands.py 
new/ovsdbapp-2.3.0/ovsdbapp/schema/open_vswitch/commands.py
--- old/ovsdbapp-2.2.1/ovsdbapp/schema/open_vswitch/commands.py 2023-02-10 
17:02:24.000000000 +0100
+++ new/ovsdbapp-2.3.0/ovsdbapp/schema/open_vswitch/commands.py 2023-04-27 
17:14:09.000000000 +0200
@@ -214,11 +214,12 @@
 class AddPortCommand(command.AddCommand):
     table_name = 'Port'
 
-    def __init__(self, api, bridge, port, may_exist):
+    def __init__(self, api, bridge, port, may_exist, **interface_attrs):
         super().__init__(api)
         self.bridge = bridge
         self.port = port
         self.may_exist = may_exist
+        self.interface_attrs = interface_attrs
 
     def run_idl(self, txn):
         br = idlutils.row_by_value(self.api.idl, 'Bridge', 'name', self.bridge)
@@ -241,6 +242,8 @@
         iface = txn.insert(self.api._tables['Interface'])
         txn.expected_ifaces.add(iface.uuid)
         iface.name = self.port
+        self.set_columns(iface, **self.interface_attrs)
+
         # This is a new port, so it won't have any existing interfaces
         port.interfaces = [iface]
         self.result = port.uuid
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/ovsdbapp-2.2.1/ovsdbapp/schema/open_vswitch/impl_idl.py 
new/ovsdbapp-2.3.0/ovsdbapp/schema/open_vswitch/impl_idl.py
--- old/ovsdbapp-2.2.1/ovsdbapp/schema/open_vswitch/impl_idl.py 2023-02-10 
17:02:24.000000000 +0100
+++ new/ovsdbapp-2.3.0/ovsdbapp/schema/open_vswitch/impl_idl.py 2023-04-27 
17:14:09.000000000 +0200
@@ -137,8 +137,9 @@
     def set_fail_mode(self, bridge, mode):
         return cmd.SetFailModeCommand(self, bridge, mode)
 
-    def add_port(self, bridge, port, may_exist=True):
-        return cmd.AddPortCommand(self, bridge, port, may_exist)
+    def add_port(self, bridge, port, may_exist=True, **interface_attrs):
+        return cmd.AddPortCommand(self, bridge, port, may_exist,
+                                  **interface_attrs)
 
     def del_port(self, port, bridge=None, if_exists=True):
         return cmd.DelPortCommand(self, port, bridge, if_exists)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ovsdbapp-2.2.1/ovsdbapp/schema/ovn_northbound/api.py 
new/ovsdbapp-2.3.0/ovsdbapp/schema/ovn_northbound/api.py
--- old/ovsdbapp-2.2.1/ovsdbapp/schema/ovn_northbound/api.py    2023-02-10 
17:02:24.000000000 +0100
+++ new/ovsdbapp-2.3.0/ovsdbapp/schema/ovn_northbound/api.py    2023-04-27 
17:14:09.000000000 +0200
@@ -40,11 +40,11 @@
     def ls_del(self, switch, if_exists=False):
         """Delete logical switch 'switch' and all its ports
 
-        :param switch:   The name or uuid of the switch
-        :type switch:    string or uuid.UUID
-        :type if_exists: If True, don't fail if the switch doesn't exist
-        :type if_exists: boolean
-        :returns:        :class:`Command` with no result
+        :param switch:    The name or uuid of the switch
+        :type switch:     string or uuid.UUID
+        :param if_exists: If True, don't fail if the switch doesn't exist
+        :type if_exists:  boolean
+        :returns:         :class:`Command` with no result
         """
 
     @abc.abstractmethod
@@ -97,6 +97,17 @@
         """
 
     @abc.abstractmethod
+    def ls_get_localnet_ports(self, switch, if_exists=False):
+        """Get localnet ports on logical switch 'switch'
+
+        :param switch:    The name or uuid of the switch
+        :type switch:     string or uuid.UUID
+        :param if_exists: If True, don't fail if the switch doesn't exist
+        :type if_exists:  boolean
+        :returns: :class:`Command` with the RowView list result
+        """
+
+    @abc.abstractmethod
     def acl_add(self, switch, direction, priority, match, action, log=False):
         """Add an ACL to 'switch'
 
@@ -1386,3 +1397,72 @@
         :type meter:   string or uuid.UUID
         :returns:      :class:`Command` with RowView result
         """
+
+    @abc.abstractmethod
+    def bfd_add(self, logical_port, dst_ip, min_tx=None, min_rx=None,
+                detect_mult=None, external_ids=None, options=None,
+                may_exist=False):
+        """Create a BFD entry
+
+        :param logical_port: Name of logical port where BFD engine should run.
+        :type logical_port:  str
+        :param dst_ip:       BFD peer IP address.
+        :type dst_ip:        str
+        :param min_tx:       This is the minimum interval, in milliseconds,
+                             that the local system would like to use when
+                             transmitting BFD Control packets, less any jitter
+                             applied. The value zero is reserved. Default value
+                             is 1000 ms.
+        :type min_tx:        Optional[int]
+        :param min_rx:       This is the minimum interval, in milliseconds,
+                             between received BFD Control packets that this
+                             system is capable of supporting, less any jitter
+                             applied by the sender. If this value is zero, the
+                             transmitting system does not want the remote
+                             system to send any periodic BFD Control packets.
+        :type min_rx:        Optional[int]
+        :param detect_mult:  Detection time multiplier.  The negotiated
+                             transmit interval, multiplied by this value,
+                             provides the Detection Time for the receiving
+                             system in Asynchronous mode. Default value is 5.
+        :type detect_mult:   Optional[int]
+        :param external_ids: Values to be added as external_id pairs.
+        :type external_ids:  Optional[Dict[str,str]]
+        :param options:      Reserved for future use.
+        :type options:       Optional[Dict[str,str]]
+        :param may_exist:    If True, update any existing BFD entry if it
+                             already exists.  Default is False which will raise
+                             an error if a BFD entry with same logical_port,
+                             dst_ip pair already exists.
+        :type may_exist:     Optional[bool]
+        :returns:            :class:`Command` with RowView result
+        """
+
+    @abc.abstractmethod
+    def bfd_del(self, uuid):
+        """Delete a BFD entry
+
+        :param uuid:   The uuid of the BFD entry
+        :type uuid:    uuid.UUID
+        :returns:      :class:`Command` with no result
+        """
+
+    @abc.abstractmethod
+    def bfd_find(self, logical_port, dst_ip):
+        """Find BFD entry.
+
+        :param logical_port: Name of logical port where BFD engine runs.
+        :type logical_port:  str
+        :param dst_ip:       BFD peer IP address.
+        :type dst_ip:        str
+        :returns:            :class:`Command` with List[Dict[str,any]] result
+        """
+
+    @abc.abstractmethod
+    def bfd_get(self, uuid):
+        """Get the BFD entry
+
+        :param uuid:   The uuid of the BFD entry
+        :type uuid:    uuid.UUID
+        :returns:      :class:`Command` with RowView result
+        """
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/ovsdbapp-2.2.1/ovsdbapp/schema/ovn_northbound/commands.py 
new/ovsdbapp-2.3.0/ovsdbapp/schema/ovn_northbound/commands.py
--- old/ovsdbapp-2.2.1/ovsdbapp/schema/ovn_northbound/commands.py       
2023-02-10 17:02:24.000000000 +0100
+++ new/ovsdbapp-2.3.0/ovsdbapp/schema/ovn_northbound/commands.py       
2023-04-27 17:14:09.000000000 +0200
@@ -80,6 +80,28 @@
     table = 'Logical_Switch'
 
 
+class LSGetLocalnetPortsCommand(cmd.ReadOnlyCommand):
+    def __init__(self, api, switch, if_exists=False):
+        super().__init__(api)
+        self.switch = switch
+        self.if_exists = if_exists
+
+    def localnet_port(self, row):
+        return row.type == const.LOCALNET
+
+    def run_idl(self, txn):
+        try:
+            lswitch = self.api.lookup('Logical_Switch', self.switch)
+            self.result = [rowview.RowView(p) for p in lswitch.ports
+                           if self.localnet_port(p)]
+        except idlutils.RowNotFound as e:
+            if self.if_exists:
+                self.result = []
+                return
+            msg = "Logical Switch %s does not exist" % self.switch
+            raise RuntimeError(msg) from e
+
+
 class _AclAddHelper(cmd.AddCommand):
     table_name = 'ACL'
 
@@ -1023,6 +1045,98 @@
             lrp.delvalue('networks', network)
 
 
+class BFDFindCommand(cmd.DbFindCommand):
+    table = 'BFD'
+
+    def __init__(self, api, port, dst_ip):
+        super().__init__(
+            api,
+            self.table,
+            ('logical_port', '=', port),
+            ('dst_ip', '=', dst_ip),
+            row=True,
+        )
+
+
+class BFDAddCommand(cmd.AddCommand):
+    # cmd.AddCommand uses self.table_name, other base commands use self.table
+    table_name = 'BFD'
+
+    def __init__(self, api, logical_port, dst_ip, min_tx=None, min_rx=None,
+                 detect_mult=None, external_ids=None, options=None,
+                 may_exist=False):
+        for attr in ('logical_port', 'dst_ip'):
+            if not isinstance(locals().get(attr), str):
+                raise ValueError("%s must be of type str" % attr)
+        for attr in ('min_tx', 'min_rx', 'detect_mult'):
+            value = locals().get(attr)
+            if value and (not isinstance(value, int) or value < 1):
+                raise ValueError("%s must be of type int and > 0" % attr)
+        for attr in ('external_ids', 'options'):
+            value = locals().get(attr)
+            if value and not isinstance(value, dict):
+                raise ValueError("%s must be of type dict" % attr)
+        super().__init__(api)
+        self.logical_port = logical_port
+        self.dst_ip = dst_ip
+        self.columns = {
+            'logical_port': logical_port,
+            'dst_ip': dst_ip,
+            'min_tx': [min_tx] if min_tx else [],
+            'min_rx': [min_rx] if min_rx else [],
+            'detect_mult': [detect_mult] if detect_mult else [],
+            'external_ids': external_ids or {},
+            'options': options or {},
+        }
+        self.may_exist = may_exist
+
+    def run_idl(self, txn):
+        cmd = BFDFindCommand(self.api, self.logical_port, self.dst_ip)
+        cmd.run_idl(txn)
+        bfd_result = cmd.result
+        if bfd_result:
+            if len(bfd_result) > 1:
+                # With the current database schema, this cannot happen, but
+                # better safe than sorry.
+                raise RuntimeError(
+                    "Unexpected duplicates in database for port %s "
+                    "and dst_ip %s" % (self.logical_port, self.dst_ip))
+            bfd = bfd_result[0]
+            if self.may_exist:
+                self.set_columns(bfd, **self.columns)
+                # When no changes are made to a record, the parent
+                # `post_commit` method will not be called.
+                #
+                # Ensure consistent return to caller of `Command.execute()`
+                # even when no changes have been applied.
+                self.result = rowview.RowView(bfd)
+                return
+            else:
+                raise RuntimeError(
+                    "BFD entry for port %s and dst_ip %s exists" % (
+                        self.logical_port, self.dst_ip))
+        bfd = txn.insert(self.api.tables[self.table_name])
+        bfd.logical_port = self.logical_port
+        bfd.dst_ip = self.dst_ip
+        self.set_columns(bfd, **self.columns)
+        # Setting the result to something other than a :class:`rowview.RowView`
+        # or :class:`ovs.db.idl.Row` typed value will make the parent
+        # `post_commit` method retrieve the newly insterted row from IDL and
+        # return that to the caller.
+        self.result = bfd.uuid
+
+
+class BFDDelCommand(cmd.DbDestroyCommand):
+    table = 'BFD'
+
+    def __init__(self, api, uuid):
+        super().__init__(api, self.table, uuid)
+
+
+class BFDGetCommand(cmd.BaseGetRowCommand):
+    table = 'BFD'
+
+
 class LrRouteAddCommand(cmd.BaseCommand):
     def __init__(self, api, router, prefix, nexthop, port=None,
                  policy='dst-ip', may_exist=False):
@@ -1459,7 +1573,7 @@
         hc = txn.insert(self.api.tables[self.table_name])
         hc.vip = self.vip
         hc.options = self.options
-        self.result = hc
+        self.result = hc.uuid
 
 
 class HealthCheckSetOptionsCommand(cmd.BaseSetOptionsCommand):
@@ -1749,7 +1863,7 @@
         gwc.chassis_name = self.chassis_name
         gwc.priority = self.priority
         self.set_columns(gwc, **self.columns)
-        self.result = gwc
+        self.result = gwc.uuid
 
 
 class HAChassisGroupAddCommand(cmd.AddCommand):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/ovsdbapp-2.2.1/ovsdbapp/schema/ovn_northbound/impl_idl.py 
new/ovsdbapp-2.3.0/ovsdbapp/schema/ovn_northbound/impl_idl.py
--- old/ovsdbapp-2.2.1/ovsdbapp/schema/ovn_northbound/impl_idl.py       
2023-02-10 17:02:24.000000000 +0100
+++ new/ovsdbapp-2.3.0/ovsdbapp/schema/ovn_northbound/impl_idl.py       
2023-04-27 17:14:09.000000000 +0200
@@ -53,6 +53,9 @@
         return self.db_remove('Logical_Switch', switch_uuid, 'dns_records',
                               dns_uuid, if_exists=if_exists)
 
+    def ls_get_localnet_ports(self, switch, if_exists=False):
+        return cmd.LSGetLocalnetPortsCommand(self, switch, if_exists)
+
     def acl_add(self, switch, direction, priority, match, action, log=False,
                 may_exist=False, **external_ids):
         return cmd.AclAddCommand(self, switch, direction, priority,
@@ -412,3 +415,20 @@
 
     def meter_get(self, meter):
         return cmd.MeterGetCommand(self, meter)
+
+    def bfd_add(self, logical_port, dst_ip, min_tx=None, min_rx=None,
+                detect_mult=None, external_ids=None, options=None,
+                may_exist=False):
+        return cmd.BFDAddCommand(self, logical_port, dst_ip, min_tx=min_tx,
+                                 min_rx=min_rx, detect_mult=detect_mult,
+                                 external_ids=external_ids, options=options,
+                                 may_exist=may_exist)
+
+    def bfd_del(self, uuid):
+        return cmd.BFDDelCommand(self, uuid)
+
+    def bfd_find(self, logical_port, dst_ip):
+        return cmd.BFDFindCommand(self, logical_port, dst_ip)
+
+    def bfd_get(self, uuid):
+        return cmd.BFDGetCommand(self, uuid)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/ovsdbapp-2.2.1/ovsdbapp/tests/functional/schema/open_vswitch/test_common_db.py
 
new/ovsdbapp-2.3.0/ovsdbapp/tests/functional/schema/open_vswitch/test_common_db.py
--- 
old/ovsdbapp-2.2.1/ovsdbapp/tests/functional/schema/open_vswitch/test_common_db.py
  2023-02-10 17:02:24.000000000 +0100
+++ 
new/ovsdbapp-2.3.0/ovsdbapp/tests/functional/schema/open_vswitch/test_common_db.py
  2023-04-27 17:14:09.000000000 +0200
@@ -113,3 +113,43 @@
             'Queue', external_ids={'x': 'x'}).execute(check_error=True)
         self.assertIsInstance(row, rowview.RowView)
         self.api.db_destroy('Queue', row.uuid).execute(check_error=True)
+
+    def test_db_set_args(self):
+        brname = self.bridges[0]['name']
+        br = self.api.lookup('Bridge', brname)
+        ext_ids = {'test': 'value'}
+        self.api.db_set('Bridge', brname,
+                        ('external_ids', ext_ids)).execute(check_error=True)
+        self.assertEqual(ext_ids, br.external_ids)
+
+    def test_db_set_kwargs(self):
+        brname = self.bridges[0]['name']
+        br = self.api.lookup('Bridge', brname)
+        ext_ids = {'test': 'value'}
+        self.api.db_set('Bridge', brname,
+                        external_ids=ext_ids).execute(check_error=True)
+        self.assertEqual(ext_ids, br.external_ids)
+
+    def test_db_set_if_exists(self):
+        brname = self.bridges[0]['name']
+        br = self.api.lookup('Bridge', brname)
+        ext_ids = {'test': 'value'}
+        self.api.db_set('Bridge', brname, if_exists=True,
+                        external_ids=ext_ids).execute(check_error=True)
+        self.assertEqual(ext_ids, br.external_ids)
+
+    def test_db_set_if_exists_missing(self):
+        brname = "missing_bridge"
+        ext_ids = {'test': 'value'}
+        # Just ensure that this completes without throwing an exception
+        self.api.db_set('Bridge', brname, if_exists=True,
+                        external_ids=ext_ids).execute(check_error=True)
+
+    def test_db_set_args_and_kwrags(self):
+        brname = self.bridges[0]['name']
+        br = self.api.lookup('Bridge', brname)
+        ext_ids = {'test': 'value'}
+        ext_ids2 = {'test2': 'value2'}
+        self.api.db_set('Bridge', brname, ('external_ids', ext_ids),
+                        external_ids=ext_ids2).execute(check_error=True)
+        self.assertEqual(ext_ids, br.external_ids)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/ovsdbapp-2.2.1/ovsdbapp/tests/functional/schema/open_vswitch/test_impl_idl.py
 
new/ovsdbapp-2.3.0/ovsdbapp/tests/functional/schema/open_vswitch/test_impl_idl.py
--- 
old/ovsdbapp-2.2.1/ovsdbapp/tests/functional/schema/open_vswitch/test_impl_idl.py
   2023-02-10 17:02:24.000000000 +0100
+++ 
new/ovsdbapp-2.3.0/ovsdbapp/tests/functional/schema/open_vswitch/test_impl_idl.py
   2023-04-27 17:14:09.000000000 +0200
@@ -87,18 +87,31 @@
         exists = self.api.br_exists(self.brname).execute(check_error=True)
         self.assertFalse(exists)
 
-    def _test_add_port(self):
+    def _test_add_port(self, **interface_attrs):
         pname = utils.get_rand_device_name()
         with self.api.transaction(check_error=True) as txn:
             txn.extend([self.api.add_br(self.brname),
-                        self.api.add_port(self.brname, pname)])
+                        self.api.add_port(self.brname, pname,
+                                          **interface_attrs)])
         return pname
 
     def test_add_port(self):
-        pname = self._test_add_port()
+        interface_attrs = {'external_ids': {'iface-id': 'port_iface-id'},
+                           'type': 'internal'}
+        pname = self._test_add_port(**interface_attrs)
         plist_cmd = self.api.list_ports(self.brname)
         ports = plist_cmd.execute(check_error=True)
         self.assertIn(pname, ports)
+        with self.api.transaction(check_error=True) as txn:
+            external_ids = txn.add(self.api.db_get('Interface', pname,
+                                                   'external_ids'))
+            _type = txn.add(self.api.db_get('Interface', pname, 'type'))
+        self.assertEqual(interface_attrs['external_ids'], external_ids.result)
+        self.assertEqual(interface_attrs['type'], _type.result)
+
+    def test_add_port_wrong_interface_attrs(self):
+        interface_attrs = {'invalid_interface_field': 'value'}
+        self.assertRaises(KeyError, self._test_add_port, **interface_attrs)
 
     def test_add_port_may_exist_false(self):
         pname = self._test_add_port()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/ovsdbapp-2.2.1/ovsdbapp/tests/functional/schema/ovn_northbound/test_impl_idl.py
 
new/ovsdbapp-2.3.0/ovsdbapp/tests/functional/schema/ovn_northbound/test_impl_idl.py
--- 
old/ovsdbapp-2.2.1/ovsdbapp/tests/functional/schema/ovn_northbound/test_impl_idl.py
 2023-02-10 17:02:24.000000000 +0100
+++ 
new/ovsdbapp-2.3.0/ovsdbapp/tests/functional/schema/ovn_northbound/test_impl_idl.py
 2023-04-27 17:14:09.000000000 +0200
@@ -41,6 +41,11 @@
         self.assertIn(fix.obj.uuid, self.table.rows)
         return fix.obj
 
+    def _lsp_add(self, switch, name, *args, **kwargs):
+        name = utils.get_rand_device_name() if name is None else name
+        self.api.lsp_add(switch.uuid, name, *args, **kwargs).execute(
+            check_error=True)
+
     def _test_ls_get(self, col):
         ls = self._ls_add(switch=utils.get_rand_device_name())
         val = getattr(ls, col)
@@ -102,6 +107,30 @@
         switch_set = set(self.api.ls_list().execute(check_error=True))
         self.assertTrue(switches.issubset(switch_set))
 
+    def test_ls_get_localnet_ports(self):
+        ls = self._ls_add()
+        self._lsp_add(ls, None, type=const.LOCALNET)
+        localnet_ports = self.api.ls_get_localnet_ports(ls.uuid).execute(
+            check_error=True)
+        self.assertEqual(ls.ports, localnet_ports)
+
+    def test_ls_get_localnet_ports_no_ports(self):
+        ls = self._ls_add()
+        localnet_ports = self.api.ls_get_localnet_ports(ls.uuid).execute(
+            check_error=True)
+        self.assertEqual([], localnet_ports)
+
+    def test_ls_get_localnet_ports_no_exist(self):
+        name = utils.get_rand_device_name()
+        cmd = self.api.ls_get_localnet_ports(name)
+        self.assertRaises(RuntimeError, cmd.execute, check_error=True)
+
+    def test_ls_get_localnet_ports_if_exists(self):
+        name = utils.get_rand_device_name()
+        localnet_ports = self.api.ls_get_localnet_ports(
+            name, if_exists=True).execute(check_error=True)
+        self.assertEqual([], localnet_ports)
+
 
 class TestAclOps(OvnNorthboundTest):
     def setUp(self):
@@ -2395,3 +2424,105 @@
 
     def test_meter_get_name(self):
         self._meter_get('name')
+
+
+class TestBFDOps(OvnNorthboundTest):
+
+    def setUp(self):
+        super(TestBFDOps, self).setUp()
+        self.table = self.api.tables['BFD']
+
+    def _bfd_add(self, *args, **kwargs):
+        cmd = self.api.bfd_add(*args, **kwargs)
+        row = cmd.execute(check_error=True)
+        self.assertEqual(cmd.logical_port, row.logical_port)
+        self.assertEqual(cmd.dst_ip, row.dst_ip)
+        self.assertEqual(cmd.columns['min_tx'] if cmd.columns[
+            'min_tx'] else [], row.min_tx)
+        self.assertEqual(cmd.columns['min_rx'] if cmd.columns[
+            'min_rx'] else [], row.min_rx)
+        self.assertEqual(cmd.columns['detect_mult'] if cmd.columns[
+            'detect_mult'] else [], row.detect_mult)
+        self.assertEqual(cmd.columns['external_ids'] or {}, row.external_ids)
+        self.assertEqual(cmd.columns['options'] or {}, row.options)
+        return idlutils.frozen_row(row)
+
+    def test_bfd_add(self):
+        name = utils.get_rand_name()
+        self._bfd_add(name, name)
+
+    def test_bfd_add_non_defaults(self):
+        name = utils.get_rand_name()
+        self._bfd_add(
+            name,
+            name,
+            min_rx=1,
+            min_tx=2,
+            detect_mult=3,
+            external_ids={'a': 'A'},
+            options={'b': 'B'},
+            may_exist=True,
+        )
+
+    def test_bfd_add_duplicate(self):
+        name = utils.get_rand_name()
+        cmd = self.api.bfd_add(name, name)
+        cmd.execute(check_error=True)
+        self.assertRaises(RuntimeError, cmd.execute, check_error=True)
+
+    def test_bfd_add_may_exist_no_change(self):
+        name = utils.get_rand_name()
+        b1 = self._bfd_add(name, name)
+        b2 = self._bfd_add(name, name, may_exist=True)
+        self.assertEqual(b1, b2)
+
+    def test_bfd_add_may_exist_change(self):
+        name = utils.get_rand_name()
+        b1 = self._bfd_add(name, name)
+        b2 = self._bfd_add(
+            name,
+            name,
+            min_rx=11,
+            min_tx=22,
+            detect_mult=33,
+            external_ids={'aa': 'AA'},
+            options={'bb': 'BB'},
+            may_exist=True,
+        )
+        self.assertNotEqual(b1, b2)
+        self.assertEqual(b1.uuid, b2.uuid)
+
+    def test_bfd_del(self):
+        name = utils.get_rand_name()
+        b1 = self._bfd_add(name, name)
+        self.assertIn(b1.uuid, self.table.rows)
+        self.api.bfd_del(b1.uuid).execute(check_error=True)
+        self.assertNotIn(b1.uuid, self.table.rows)
+
+    def test_bfd_find(self):
+        name1 = utils.get_rand_name()
+        name2 = utils.get_rand_name()
+        b1 = self._bfd_add(name1, name1)
+        b2 = self._bfd_add(name1, name2)
+        b3 = self._bfd_add(name2, name1)
+        b4 = self._bfd_add(name2, name2)
+        self.assertIn(b1.uuid, self.table.rows)
+        self.assertIn(b2.uuid, self.table.rows)
+        self.assertIn(b3.uuid, self.table.rows)
+        self.assertIn(b4.uuid, self.table.rows)
+        found = self.api.bfd_find(
+            b1.logical_port,
+            b1.dst_ip).execute(check_error=True)
+        self.assertEqual(1, len(found))
+        self.assertEqual(b1.uuid, found[0].uuid)
+        for col in set(self.api.tables['BFD'].columns.keys()) - set(
+                ('_uuid', 'status')):
+            self.assertEqual(
+                getattr(b1, col),
+                getattr(found[0], col))
+
+    def test_bfd_get(self):
+        name = utils.get_rand_name()
+        b1 = self.api.bfd_add(name, name).execute(check_error=True)
+        b2 = self.api.bfd_get(b1.uuid).execute(check_error=True)
+        self.assertEqual(b1, b2)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/ovsdbapp-2.2.1/ovsdbapp/tests/unit/backend/ovs_idl/test_idlutils.py 
new/ovsdbapp-2.3.0/ovsdbapp/tests/unit/backend/ovs_idl/test_idlutils.py
--- old/ovsdbapp-2.2.1/ovsdbapp/tests/unit/backend/ovs_idl/test_idlutils.py     
2023-02-10 17:02:24.000000000 +0100
+++ new/ovsdbapp-2.3.0/ovsdbapp/tests/unit/backend/ovs_idl/test_idlutils.py     
2023-04-27 17:14:09.000000000 +0200
@@ -12,13 +12,20 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
+import unittest
 from unittest import mock
 
+import testscenarios
+
 from ovsdbapp import api
 from ovsdbapp.backend.ovs_idl import idlutils
+from ovsdbapp import exceptions
 from ovsdbapp.tests import base
 
 
+load_tests = testscenarios.load_tests_apply_scenarios
+
+
 class MockColumn(object):
     def __init__(self, name, type, is_optional=False, test_value=None):
         self.name = name
@@ -191,6 +198,76 @@
         self.assertRaises(AssertionError, idlutils.index_name)
 
 
+class TestWaitForChange(base.TestCase):
+    assertRaises = unittest.TestCase.assertRaises  # context manager support
+    scenarios = testscenarios.multiply_scenarios([
+        ('seqno matches', dict(seqno_eq=True)),
+        ('seqno unmatched', dict(seqno_eq=False)),
+    ], [
+        ('Idl.run returns False', dict(run_=False)),
+        ('Idl.run returns True', dict(run_=True)),
+    ], [
+        ('timeout is None', dict(timeout=None)),
+        ('timeout is negative', dict(timeout=-1)),
+        ('timeout is zero', dict(timeout=0)),
+        ('timeout is positive', dict(timeout=1)),
+    ], [
+        ('timeout not elapsed', dict(timed_out=False)),
+        ('timeout is elapsed', dict(timed_out=True)),
+    ])
+
+    def _make_idl_mock(self):
+        idl = mock.MagicMock()
+        idl.change_seqno = 42
+        idl.run.return_value = self.run_
+        idl.wait.side_effect = [None, None, StopIteration]
+        return idl
+
+    def test_wait_for_change(self):
+        timeout = self.timeout and self.timeout > 0
+        exc_raised = False
+        if self.seqno_eq and not self.run_:
+            if not timeout or not self.timed_out:
+                exc_raised = StopIteration
+            elif timeout and self.timed_out:
+                exc_raised = exceptions.TimeoutException
+
+        expected = {
+            'idl_wait': self.seqno_eq and not self.run_,
+            'timer_wait': self.seqno_eq and not self.run_ and timeout,
+            'exc_raised': exc_raised}
+
+        Idl = self._make_idl_mock()
+        now = 228399780
+        if timeout:
+            end_time = now + self.timeout - int(not self.timed_out)
+        else:
+            end_time = Exception
+        poller_inst = mock.MagicMock()
+        seqno = Idl.change_seqno if self.seqno_eq else Idl.change_seqno - 1
+
+        @mock.patch.object(idlutils.time, 'time', side_effect=[now, end_time])
+        @mock.patch.object(idlutils.poller, 'Poller', return_value=poller_inst)
+        def do_test(_poll_mock, _time_mock):
+            if expected['exc_raised']:
+                with self.assertRaises(expected['exc_raised']):
+                    idlutils.wait_for_change(Idl, self.timeout, seqno)
+            else:
+                idlutils.wait_for_change(Idl, self.timeout, seqno)
+
+            if expected['idl_wait']:
+                Idl.wait.assert_called()
+            else:
+                Idl.wait.assert_not_called()
+
+            if expected['timer_wait']:
+                poller_inst.timer_wait.assert_called()
+            else:
+                poller_inst.timer_wait.assert_not_called()
+
+        do_test()
+
+
 class TestMergeIntersection(base.TestCase):
     def test_no_args(self):
         result = idlutils.merge_intersection()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ovsdbapp-2.2.1/ovsdbapp.egg-info/PKG-INFO 
new/ovsdbapp-2.3.0/ovsdbapp.egg-info/PKG-INFO
--- old/ovsdbapp-2.2.1/ovsdbapp.egg-info/PKG-INFO       2023-02-10 
17:02:53.000000000 +0100
+++ new/ovsdbapp-2.3.0/ovsdbapp.egg-info/PKG-INFO       2023-04-27 
17:14:39.000000000 +0200
@@ -1,6 +1,6 @@
 Metadata-Version: 1.2
 Name: ovsdbapp
-Version: 2.2.1
+Version: 2.3.0
 Summary: A library for creating OVSDB applications
 Home-page: https://pypi.org/project/ovsdbapp/
 Author: OpenStack
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ovsdbapp-2.2.1/ovsdbapp.egg-info/SOURCES.txt 
new/ovsdbapp-2.3.0/ovsdbapp.egg-info/SOURCES.txt
--- old/ovsdbapp-2.2.1/ovsdbapp.egg-info/SOURCES.txt    2023-02-10 
17:02:54.000000000 +0100
+++ new/ovsdbapp-2.3.0/ovsdbapp.egg-info/SOURCES.txt    2023-04-27 
17:14:39.000000000 +0200
@@ -128,6 +128,7 @@
 releasenotes/notes/provide-lrp-gateway-chassis-api-14e2948183f60cfa.yaml
 releasenotes/notes/provide-lrp-get-method-a33a99a7f86b827e.yaml
 releasenotes/notes/provide-lrp-networks-modifying-1af13589064c12c6.yaml
+releasenotes/source/2023.1.rst
 releasenotes/source/conf.py
 releasenotes/source/index.rst
 releasenotes/source/pike.rst
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ovsdbapp-2.2.1/ovsdbapp.egg-info/pbr.json 
new/ovsdbapp-2.3.0/ovsdbapp.egg-info/pbr.json
--- old/ovsdbapp-2.2.1/ovsdbapp.egg-info/pbr.json       2023-02-10 
17:02:53.000000000 +0100
+++ new/ovsdbapp-2.3.0/ovsdbapp.egg-info/pbr.json       2023-04-27 
17:14:39.000000000 +0200
@@ -1 +1 @@
-{"git_version": "7733f0c", "is_release": true}
\ No newline at end of file
+{"git_version": "770f77d", "is_release": true}
\ No newline at end of file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ovsdbapp-2.2.1/releasenotes/source/2023.1.rst 
new/ovsdbapp-2.3.0/releasenotes/source/2023.1.rst
--- old/ovsdbapp-2.2.1/releasenotes/source/2023.1.rst   1970-01-01 
01:00:00.000000000 +0100
+++ new/ovsdbapp-2.3.0/releasenotes/source/2023.1.rst   2023-04-27 
17:14:09.000000000 +0200
@@ -0,0 +1,6 @@
+===========================
+2023.1 Series Release Notes
+===========================
+
+.. release-notes::
+   :branch: stable/2023.1
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ovsdbapp-2.2.1/releasenotes/source/index.rst 
new/ovsdbapp-2.3.0/releasenotes/source/index.rst
--- old/ovsdbapp-2.2.1/releasenotes/source/index.rst    2023-02-10 
17:02:24.000000000 +0100
+++ new/ovsdbapp-2.3.0/releasenotes/source/index.rst    2023-04-27 
17:14:09.000000000 +0200
@@ -6,6 +6,7 @@
    :maxdepth: 1
 
    unreleased
+   2023.1
    zed
    yoga
    xena
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ovsdbapp-2.2.1/tools/setup-ovs.sh 
new/ovsdbapp-2.3.0/tools/setup-ovs.sh
--- old/ovsdbapp-2.2.1/tools/setup-ovs.sh       2023-02-10 17:02:24.000000000 
+0100
+++ new/ovsdbapp-2.3.0/tools/setup-ovs.sh       2023-04-27 17:14:09.000000000 
+0200
@@ -1,25 +1,16 @@
 #!/bin/bash -xe
 
-OVS_BRANCH=${OVS_BRANCH:-master}
 OVN_BRANCH=${OVN_BRANCH:-main}
 
-function use_new_ovn_repository {
-    # If OVN_BRANCH > branch-2.12 return 0
-    return $(! printf "%s\n%s" $OVN_BRANCH branch-2.12 | sort -C -V)
-}
-
-# We require at least OVS 2.7. Testing infrastructure doesn't support it yet,
-# so build it. Eventually, we should run some checks to see what is actually
-# installed and see if we can use it instead.
-if [ "$OVS_SRCDIR" -a ! -d "$OVS_SRCDIR" ]; then
-    echo "Building OVS branch $OVS_BRANCH in $OVS_SRCDIR"
-    mkdir -p $OVS_SRCDIR
-    git clone https://github.com/openvswitch/ovs.git $OVS_SRCDIR
-    (cd $OVS_SRCDIR && git checkout $OVS_BRANCH && ./boot.sh && 
PYTHON=/usr/bin/python ./configure && make -j$(($(nproc) + 1)))
-fi
-if use_new_ovn_repository && [ "$OVN_SRCDIR" -a ! -d "$OVN_SRCDIR" ]; then
+if [ "$OVN_SRCDIR" -a ! -d "$OVN_SRCDIR" ]; then
     echo "Building OVN branch $OVN_BRANCH in $OVN_SRCDIR"
     mkdir -p $OVN_SRCDIR
-    git clone https://github.com/ovn-org/ovn.git $OVN_SRCDIR
-    (cd $OVN_SRCDIR && git checkout $OVN_BRANCH && ./boot.sh && 
PYTHON=/usr/bin/python ./configure --with-ovs-source=$OVS_SRCDIR && make 
-j$(($(nproc) + 1)))
+    git clone --recurse-submodules https://github.com/ovn-org/ovn.git 
$OVN_SRCDIR
+    pushd $OVN_SRCDIR
+    git checkout $OVN_BRANCH
+    pushd ovs
+    ./boot.sh && PYTHON=/usr/bin/python ./configure && make -j$(($(nproc) + 1))
+    popd
+    ./boot.sh && PYTHON=/usr/bin/python ./configure && make -j$(($(nproc) + 1))
+    popd
 fi
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ovsdbapp-2.2.1/tox.ini new/ovsdbapp-2.3.0/tox.ini
--- old/ovsdbapp-2.2.1/tox.ini  2023-02-10 17:02:24.000000000 +0100
+++ new/ovsdbapp-2.3.0/tox.ini  2023-04-27 17:14:09.000000000 +0200
@@ -9,7 +9,6 @@
 setenv =
    VIRTUAL_ENV={envdir}
    PYTHONWARNINGS=default::DeprecationWarning
-   OS_TEST_PATH=./ovsdbapp/tests/unit
    OS_LOG_CAPTURE={env:OS_LOG_CAPTURE:true}
    OS_STDOUT_CAPTURE={env:OS_STDOUT_CAPTURE:true}
    OS_STDERR_CAPTURE={env:OS_STDERR_CAPTURE:true}
@@ -64,10 +63,9 @@
 [testenv:functional]
 setenv = {[testenv]setenv}
          OS_TEST_PATH=./ovsdbapp/tests/functional
-         OVS_SRCDIR={envdir}/src/ovs
          OVN_SRCDIR={envdir}/src/ovn
-         VTEP_SRCDIR={envdir}/src/ovs/vtep
-         OVS_BRANCH={env:OVS_BRANCH:}
+         OVS_SRCDIR={envdir}/src/ovn/ovs
+         VTEP_SRCDIR={envdir}src/ovn/ovs/vtep
          OVN_BRANCH={env:OVN_BRANCH:}
 passenv = KEEP_VENV
 commands =

Reply via email to