From ede954f8c0b63f289139d269993a4593ffb7aa92 Mon Sep 17 00:00:00 2001 From: Nisar Khan Date: Thu, 6 Aug 2026 05:45:51 +0000 Subject: [PATCH] Add Python3.14 Support --- .travis.yml | 3 +++ opflexagent/as_metadata_manager.py | 14 ++++++++++++-- opflexagent/opflex_notify.py | 22 ++++++++++++---------- opflexagent/test/test_gbp_ovs_agent.py | 4 +++- opflexagent/test/test_gbp_vpp_agent.py | 4 +++- tox.ini | 3 ++- 6 files changed, 35 insertions(+), 15 deletions(-) diff --git a/.travis.yml b/.travis.yml index f7bfad74..138ec3b8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -18,6 +18,9 @@ matrix: - python: 3.13 env: - TOX_ENV=py313 + - python: 3.14 + env: + - TOX_ENV=py314 install: diff --git a/opflexagent/as_metadata_manager.py b/opflexagent/as_metadata_manager.py index 16f9e018..46e98ed9 100644 --- a/opflexagent/as_metadata_manager.py +++ b/opflexagent/as_metadata_manager.py @@ -44,6 +44,15 @@ LOG = logging.getLogger(__name__) + +def _get_multiprocessing_context(): + if (os.name == 'posix' and + hasattr(multiprocessing, 'get_all_start_methods') and + 'fork' in multiprocessing.get_all_start_methods()): + return multiprocessing.get_context('fork') + return multiprocessing + + gbp_opts = [ cfg.StrOpt('epg_mapping_dir', default='/var/lib/opflex-agent-ovs/endpoints/', @@ -232,7 +241,8 @@ def __init__(self, watchdir, extensions, name="Not Specified"): self.name = name self.watchdir = watchdir self.extensions = extensions.split(',') - self.eventq = multiprocessing.Queue() + self.mp_context = _get_multiprocessing_context() + self.eventq = self.mp_context.Queue() self.auto_restart_fileprocessor = True self.start_file_processor() @@ -289,7 +299,7 @@ def start_file_processor(self): self.eventq, functools.partial(self.process)) fprun = functools.partial(fp.run) - self.processor = multiprocessing.Process(target=fprun) + self.processor = self.mp_context.Process(target=fprun) self.processor.start() diff --git a/opflexagent/opflex_notify.py b/opflexagent/opflex_notify.py index df17e352..510dbf94 100644 --- a/opflexagent/opflex_notify.py +++ b/opflexagent/opflex_notify.py @@ -175,17 +175,18 @@ def run(self): LOG.error('Run: {}'.format(e)) -def worker(initconfig=False, daemon=True): - class OpflexNotifyWorker(multiprocessing.Process): - def __init__(self): - self.agent = None - super(OpflexNotifyWorker, self).__init__() - - def run(self): - self.agent = OpflexNotifyAgent() - self.agent.run() - return +class OpflexNotifyWorker(multiprocessing.Process): + def __init__(self): + self.agent = None + super(OpflexNotifyWorker, self).__init__() + def run(self): + self.agent = OpflexNotifyAgent() + self.agent.run() + return + + +def worker(initconfig=False, daemon=True): worker = None try: if initconfig: @@ -198,6 +199,7 @@ def run(self): worker.start() except Exception as e: LOG.error('Worker Initalization: {}'.format(e)) + worker = None return worker diff --git a/opflexagent/test/test_gbp_ovs_agent.py b/opflexagent/test/test_gbp_ovs_agent.py index 657db2d9..ca95d5a8 100644 --- a/opflexagent/test/test_gbp_ovs_agent.py +++ b/opflexagent/test/test_gbp_ovs_agent.py @@ -109,6 +109,7 @@ def start(self, interval=0): mock.patch('neutron.agent.common.ovs_lib.BaseOVS.get_bridges'), mock.patch('oslo_service.loopingcall.FixedIntervalLoopingCall', new=MockFixedIntervalLoopingCall), + mock.patch('opflexagent.opflex_notify.worker', return_value=None), mock.patch('opflexagent.gbp_agent.GBPOpflexAgent.' '_report_state')] @@ -145,7 +146,8 @@ def _mock_agent(self, agent): agent.bridge_manager.trunk_rpc = mock.Mock() agent.of_rpc.get_gbp_details = mock.Mock() agent.port_manager.of_rpc.request_endpoint_details_list = mock.Mock() - agent.notify_worker.terminate() + if agent.notify_worker is not None: + agent.notify_worker.terminate() def test_port_unbound_snat_cleanup(self): self.agent.int_br = mock.Mock() diff --git a/opflexagent/test/test_gbp_vpp_agent.py b/opflexagent/test/test_gbp_vpp_agent.py index 7bd95b26..36caa70b 100755 --- a/opflexagent/test/test_gbp_vpp_agent.py +++ b/opflexagent/test/test_gbp_vpp_agent.py @@ -96,6 +96,7 @@ def start(self, interval=0): resources = [ mock.patch('oslo_service.loopingcall.FixedIntervalLoopingCall', new=MockFixedIntervalLoopingCall), + mock.patch('opflexagent.opflex_notify.worker', return_value=None), mock.patch('opflexagent.gbp_agent.GBPOpflexAgent.' '_report_state'), mock.patch('opflexagent.as_metadata_manager.' @@ -136,7 +137,8 @@ def _mock_agent(self, agent): agent.bridge_manager.trunk_rpc = mock.Mock() agent.of_rpc.get_gbp_details = mock.Mock() agent.port_manager.of_rpc.request_endpoint_details_list = mock.Mock() - agent.notify_worker.terminate() + if agent.notify_worker is not None: + agent.notify_worker.terminate() def test_port_unbound_snat_cleanup(self): self.agent.int_br = mock.Mock() diff --git a/tox.ini b/tox.ini index ffd11b5d..bbc092bb 100644 --- a/tox.ini +++ b/tox.ini @@ -1,5 +1,5 @@ [tox] -envlist = py310,py311,py312,py313,pep8 +envlist = py310,py311,py312,py313,py314,pep8 minversion = 2.3.2 skipsdist = False @@ -9,6 +9,7 @@ basepython = py311: python3.11 py312: python3.12 py313: python3.13 + py314: python3.14 pep8: python3.10 setenv = VIRTUAL_ENV={envdir} OS_LOG_CAPTURE={env:OS_LOG_CAPTURE:true}