From ae74b483c3b9533d4f92d5b0b1210f35c896d2d2 Mon Sep 17 00:00:00 2001 From: Rodolfo Alonso Hernandez Date: Tue, 2 Jun 2020 11:10:21 +0000 Subject: [PATCH] Make NeutronOvsdbIdl singleton "NeutronOvsdbIdl" should be a singleton class; only one instance should be shared everywhere is called. Currently the connection and the "OvsIdlMonitor" instances are global; those instances are used to declare the "NeutronOvsdbIdl" instance. As commented in the related bug, this singleton will ensure that the OvsIdl indexes are created just once. Related-Bug: #1881424 Conflicts: neutron/common/utils.py neutron/agent/ovsdb/impl_idl.py Change-Id: I639cf673a983b7b1be810495d8a8c2d89919a9b6 (cherry picked from commit 178227c8b6636433fcdab4dfd342468335b76aa6) (cherry picked from commit c874c44cdc0dc32ae1bdcedfce4a2a9319d8e1eb) --- neutron/agent/ovsdb/impl_idl.py | 4 +++- neutron/common/utils.py | 12 ++++++++++++ neutron/tests/unit/common/test_utils.py | 18 ++++++++++++++++++ 3 files changed, 33 insertions(+), 1 deletion(-) diff --git a/neutron/agent/ovsdb/impl_idl.py b/neutron/agent/ovsdb/impl_idl.py index 603102583d1..25256687859 100644 --- a/neutron/agent/ovsdb/impl_idl.py +++ b/neutron/agent/ovsdb/impl_idl.py @@ -22,6 +22,7 @@ from ovsdbapp.backend.ovs_idl import vlog from ovsdbapp.schema.open_vswitch import impl_idl from neutron.agent.ovsdb.native import connection as n_connection +from neutron.common import utils from neutron.conf.agent import ovs_conf from neutron.plugins.ml2.drivers.openvswitch.agent.common import constants @@ -83,12 +84,13 @@ class OvsCleanup(command.BaseCommand): return True +@utils.SingletonDecorator class NeutronOvsdbIdl(impl_idl.OvsdbIdl): def __init__(self, connection, idl_monitor): max_level = None if cfg.CONF.OVS.ovsdb_debug else vlog.INFO vlog.use_python_logger(max_level=max_level) self.idl_monitor = idl_monitor - super(NeutronOvsdbIdl, self).__init__(connection) + impl_idl.OvsdbIdl.__init__(self, connection) def ovs_cleanup(self, bridges, all_ports=False): return OvsCleanup(self, bridges, all_ports) diff --git a/neutron/common/utils.py b/neutron/common/utils.py index cc2685b4785..bff10bc40a2 100644 --- a/neutron/common/utils.py +++ b/neutron/common/utils.py @@ -982,3 +982,15 @@ def timecost(f): ret = f(*args, **kwargs) return ret return wrapper + + +class SingletonDecorator(object): + + def __init__(self, klass): + self._klass = klass + self._instance = None + + def __call__(self, *args, **kwargs): + if self._instance is None: + self._instance = self._klass(*args, **kwargs) + return self._instance diff --git a/neutron/tests/unit/common/test_utils.py b/neutron/tests/unit/common/test_utils.py index 80461253980..be373964d05 100644 --- a/neutron/tests/unit/common/test_utils.py +++ b/neutron/tests/unit/common/test_utils.py @@ -624,3 +624,21 @@ class SpawnWithOrWithoutProfilerTestCase( def test_spawn_without_profiler(self): self._compare_profilers_in_parent_and_in_child(init_profiler=False) + + +@utils.SingletonDecorator +class _TestSingletonClass(object): + + def __init__(self): + self.variable = None + + +class SingletonDecoratorTestCase(base.BaseTestCase): + + def test_singleton_instance_class(self): + instance_1 = _TestSingletonClass() + instance_1.variable = 'value1' + + instance_2 = _TestSingletonClass() + self.assertEqual(instance_1.__hash__(), instance_2.__hash__()) + self.assertEqual('value1', instance_2.variable)