Drop Windows platform support from ovsdbapp

Open vSwitch 4.0.0 removes Windows support [1], including ``python-ovs``
helpers such as ``winutils`` used by ovsdbapp's Windows IDL connection
code. Remove the ``windows`` backend, platform checks in ``connection``,
``idlutils.row_by_record()`` and ``vlog.use_python_logger()``, and
related unit tests. Document Unix-like platforms as the supported
target and add a release note for deployers.

[1]https://github.com/openvswitch/ovs/commit/965eb1f87a4d47be1d86483df7d93f7a37da4961

Closes-Bug: #2168950
Assisted-By: Composer 2.5
Signed-off-by: Rodolfo Alonso <rodolfo.ah@gmail.com>
Change-Id: I617c04c1b4fe48d4c5f9d336f1df0c68e6dd1039
This commit is contained in:
Rodolfo Alonso authored and Rodolfo Alonso Hernandez committed 2026-09-26 12:55:26 +02:00
1 parent 0ece018396
commit 837b38b232
10 files changed
+17 -157

No files matched your search

+4 -2
View File
@@ -8,9 +8,11 @@ ovsdbapp
A library for creating OVSDB applications
The ovdsbapp library is useful for creating applications that communicate
The ovsdbapp library is useful for creating applications that communicate
via Open_vSwitch's OVSDB protocol (https://tools.ietf.org/html/rfc7047). It
wraps the Python 'ovs' and adds an event loop and friendly transactions.
wraps the Python ``ovs`` package and adds an event loop and friendly
transactions. ovsdbapp targets Unix-like systems where Open vSwitch and
``python-ovs`` are supported.
* Free software: Apache license
* Source: https://opendev.org/openstack/ovsdbapp/
+3
View File
@@ -2,6 +2,9 @@
Installation
============
ovsdbapp is supported on Unix-like platforms with Open vSwitch and the
``python-ovs`` bindings. Microsoft Windows is not supported.
At the command line::
$ pip install ovsdbapp
+1 -6
View File
@@ -13,7 +13,6 @@
# under the License.
import logging
import os
import queue
import threading
import time
@@ -24,13 +23,9 @@ from ovs.db import idl
from ovs import poller
from ovsdbapp.backend.ovs_idl import idlutils
from ovsdbapp.backend.ovs_idl.linux import connection_utils
from ovsdbapp import exceptions
if os.name == 'nt':
from ovsdbapp.backend.ovs_idl.windows import connection_utils
else:
from ovsdbapp.backend.ovs_idl.linux import connection_utils
LOG = logging.getLogger(__name__)
+1 -11
View File
@@ -20,7 +20,6 @@ import functools
import json
import logging
import os
import sys
import time
import uuid
@@ -127,16 +126,7 @@ def row_by_record(idl_, table, record):
# Not a UUID string, continue lookup by other means
pass
except KeyError as e:
if sys.platform != 'win32':
# On Windows the name of the ports is described by the OVS schema:
# https://tinyurl.com/zk8skhx
# Is a UUID. (This is due to the fact on Windows port names don't
# have the 16 chars length limitation as for Linux). Because of
# this uuid.UUID(record) will not raise a ValueError exception
# as it happens on Linux and will try to fetch the directly
# the column instead of using the lookup table. This will raise
# a KeyError exception on Windows.
raise RowNotFound(table=table, col='uuid', match=record) from e
raise RowNotFound(table=table, col='uuid', match=record) from e
rl = _LOOKUP_TABLE.get(table, RowLookup(table, get_index_column(t), None))
# no table means uuid only, no column means lookup table only has one row
-20
View File
@@ -14,18 +14,9 @@
import collections
import logging
import sys
from ovs import vlog
try:
from eventlet import patcher
# If eventlet is installed and the 'thread' module is patched, we will
# skip setting up the python logger on Windows.
EVENTLET_NONBLOCKING_MODE_ENABLED = patcher.is_monkey_patched('thread')
except ImportError:
EVENTLET_NONBLOCKING_MODE_ENABLED = False
_LOG = logging.getLogger(__name__)
# Map local log LEVELS to local LOG functions
@@ -63,17 +54,6 @@ def use_python_logger(levels=ALL_LEVELS, max_level=None):
:param: max_level: the maximum level to log
:type: max_level: vlog level, CRITICAL, ERROR, WARN, INFO, or DEBUG
"""
if sys.platform == 'win32' and EVENTLET_NONBLOCKING_MODE_ENABLED:
# NOTE(abalutoiu) When using oslo logging we need to keep in mind that
# it does not work well with native threads. We need to be careful when
# we call eventlet.tpool.execute, and make sure that it will not use
# the oslo logging, since it might cause unexpected hangs if
# greenthreads are used. On Windows we have to use
# eventlet.tpool.execute for a call to the ovs lib which will use
# vlog to log messages. We will skip replacing the OVS IDL logger
# functions on Windows to avoid unexpected hangs with oslo logging
return
if max_level:
levels = levels[:levels.index(max_level) + 1]
Whitespace-only changes.
@@ -1,61 +0,0 @@
# Copyright 2017 Cloudbase Solutions Srl
#
# 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 ovs import poller
from ovs import winutils
from ovsdbapp.backend.ovs_idl.common import base_connection_utils
from ovsdbapp.backend.ovs_idl.windows import utils
class WaitQueue(base_connection_utils.WaitQueue):
def init_alert_notification(self):
# We will use an event to get signaled when there is something in
# the queue. The OVS poller can wait on events on Windows.
# NOTE(abalutoiu) The assumption made is that the queue has
# length 1, otherwise we will need to have a list of events with
# the size of the queue.
self.alert_event = winutils.get_new_event(bManualReset=True,
bInitialState=False)
def alert_notification_consume(self):
# Set the event object to the nonsignaled state to indicate that
# the queue is empty.
winutils.win32event.ResetEvent(self.alert_event)
def alert_notify(self):
# Set the event object to the signaled state to indicate that
# we have something in the queue.
winutils.win32event.SetEvent(self.alert_event)
@property
def alert_fileno(self):
return self.alert_event
def close(self):
pass
def monkey_patch_poller_support():
# Ensure that WaitForMultipleObjects will not block other greenthreads.
# poller.block uses WaitForMultipleObjects on Windows
old_block = poller.Poller.block
def new_block(self):
return utils.avoid_blocking_call(old_block, self)
poller.Poller.block = new_block
monkey_patch_poller_support()
-42
View File
@@ -1,42 +0,0 @@
# Copyright 2017 Cloudbase Solutions Srl
#
# 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.
try:
import eventlet
from eventlet import tpool
except ImportError:
eventlet = None
def avoid_blocking_call(f, *args, **kwargs):
"""Ensure that the method "f" will not block other greenthreads.
Performs the call to the function "f" received as parameter in a
different thread using tpool.execute when called from a greenthread.
This will ensure that the function "f" will not block other greenthreads.
If not called from a greenthread, it will invoke the function "f" directly.
The function "f" will receive as parameters the arguments "args" and
keyword arguments "kwargs". If eventlet is not installed on the system
then this will call directly the function "f".
"""
if eventlet is None:
return f(*args, **kwargs)
# Note that eventlet.getcurrent will always return a greenlet object.
# In case of a greenthread, the parent greenlet will always be the hub
# loop greenlet.
if eventlet.getcurrent().parent:
return tpool.execute(f, *args, **kwargs)
return f(*args, **kwargs)
@@ -161,8 +161,7 @@ class TestIdlUtils(base.TestCase):
obj = MockCommand("test")
self.assertEqual("test", idlutils.db_replace_record(obj))
@mock.patch('sys.platform', 'linux2')
def test_row_by_record_linux(self):
def test_row_by_record(self):
FAKE_RECORD = 'fake_record'
mock_idl_ = mock.MagicMock()
mock_table = mock.MagicMock(
@@ -174,19 +173,6 @@ class TestIdlUtils(base.TestCase):
FAKE_RECORD)
self.assertEqual(mock.sentinel.row_value, res)
@mock.patch('sys.platform', 'win32')
def test_row_by_record_win(self):
FAKE_RECORD_GUID = '7b0f349d-5524-4d36-afff-5222b9fdee8c'
mock_idl_ = mock.MagicMock()
mock_table = mock.MagicMock(
rows={mock.sentinel.row: mock.sentinel.row_value})
mock_idl_.tables = {mock.sentinel.table_name: mock_table}
res = idlutils.row_by_record(mock_idl_,
mock.sentinel.table_name,
FAKE_RECORD_GUID)
self.assertEqual(mock.sentinel.row_value, res)
def test_index_name(self):
expected = {
('one',): 'one',
@@ -0,0 +1,7 @@
---
upgrade:
- |
Support for running ovsdbapp on Microsoft Windows has been removed.
Open vSwitch removed Windows support in version 4.0.0, including the
``python-ovs`` APIs ovsdbapp relied on for Windows-specific IDL
connection handling. ovsdbapp now targets Unix-like systems only.