Merge "Windows OVS: minimize polling"
This commit is contained in:
commit
d6f6ddea38
|
@ -13,13 +13,63 @@
|
||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
import os
|
import contextlib
|
||||||
|
|
||||||
|
import eventlet
|
||||||
|
from oslo_config import cfg
|
||||||
|
from oslo_log import log as logging
|
||||||
|
|
||||||
|
from neutron.agent.common import async_process
|
||||||
|
from neutron.agent.common import base_polling
|
||||||
|
from neutron.agent.common import ovsdb_monitor
|
||||||
|
from neutron.plugins.ml2.drivers.openvswitch.agent.common import constants
|
||||||
|
|
||||||
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
if os.name == 'nt':
|
@contextlib.contextmanager
|
||||||
from neutron.agent.windows import polling
|
def get_polling_manager(minimize_polling=False,
|
||||||
else:
|
ovsdb_monitor_respawn_interval=(
|
||||||
from neutron.agent.linux import polling
|
constants.DEFAULT_OVSDBMON_RESPAWN)):
|
||||||
|
if minimize_polling:
|
||||||
|
pm = InterfacePollingMinimizer(
|
||||||
|
ovsdb_monitor_respawn_interval=ovsdb_monitor_respawn_interval)
|
||||||
|
pm.start()
|
||||||
|
else:
|
||||||
|
pm = base_polling.AlwaysPoll()
|
||||||
|
try:
|
||||||
|
yield pm
|
||||||
|
finally:
|
||||||
|
if minimize_polling:
|
||||||
|
pm.stop()
|
||||||
|
|
||||||
get_polling_manager = polling.get_polling_manager
|
|
||||||
InterfacePollingMinimizer = polling.InterfacePollingMinimizer
|
class InterfacePollingMinimizer(base_polling.BasePollingManager):
|
||||||
|
"""Monitors ovsdb to determine when polling is required."""
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
ovsdb_monitor_respawn_interval=constants.DEFAULT_OVSDBMON_RESPAWN):
|
||||||
|
|
||||||
|
super(InterfacePollingMinimizer, self).__init__()
|
||||||
|
self._monitor = ovsdb_monitor.SimpleInterfaceMonitor(
|
||||||
|
respawn_interval=ovsdb_monitor_respawn_interval,
|
||||||
|
ovsdb_connection=cfg.CONF.OVS.ovsdb_connection)
|
||||||
|
|
||||||
|
def start(self):
|
||||||
|
self._monitor.start(block=True)
|
||||||
|
|
||||||
|
def stop(self):
|
||||||
|
try:
|
||||||
|
self._monitor.stop()
|
||||||
|
except async_process.AsyncProcessException:
|
||||||
|
LOG.debug("InterfacePollingMinimizer was not running when stopped")
|
||||||
|
|
||||||
|
def _is_polling_required(self):
|
||||||
|
# Maximize the chances of update detection having a chance to
|
||||||
|
# collect output.
|
||||||
|
eventlet.sleep()
|
||||||
|
return self._monitor.has_updates
|
||||||
|
|
||||||
|
def get_events(self):
|
||||||
|
return self._monitor.get_events()
|
||||||
|
|
|
@ -1,74 +0,0 @@
|
||||||
# Copyright 2013 Red Hat, Inc.
|
|
||||||
#
|
|
||||||
# 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
|
|
||||||
|
|
||||||
import eventlet
|
|
||||||
from oslo_config import cfg
|
|
||||||
from oslo_log import log as logging
|
|
||||||
|
|
||||||
from neutron.agent.common import async_process
|
|
||||||
from neutron.agent.common import base_polling
|
|
||||||
from neutron.agent.common import ovsdb_monitor
|
|
||||||
from neutron.plugins.ml2.drivers.openvswitch.agent.common import constants
|
|
||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
|
|
||||||
@contextlib.contextmanager
|
|
||||||
def get_polling_manager(minimize_polling=False,
|
|
||||||
ovsdb_monitor_respawn_interval=(
|
|
||||||
constants.DEFAULT_OVSDBMON_RESPAWN)):
|
|
||||||
if minimize_polling:
|
|
||||||
pm = InterfacePollingMinimizer(
|
|
||||||
ovsdb_monitor_respawn_interval=ovsdb_monitor_respawn_interval)
|
|
||||||
pm.start()
|
|
||||||
else:
|
|
||||||
pm = base_polling.AlwaysPoll()
|
|
||||||
try:
|
|
||||||
yield pm
|
|
||||||
finally:
|
|
||||||
if minimize_polling:
|
|
||||||
pm.stop()
|
|
||||||
|
|
||||||
|
|
||||||
class InterfacePollingMinimizer(base_polling.BasePollingManager):
|
|
||||||
"""Monitors ovsdb to determine when polling is required."""
|
|
||||||
|
|
||||||
def __init__(
|
|
||||||
self,
|
|
||||||
ovsdb_monitor_respawn_interval=constants.DEFAULT_OVSDBMON_RESPAWN):
|
|
||||||
|
|
||||||
super(InterfacePollingMinimizer, self).__init__()
|
|
||||||
self._monitor = ovsdb_monitor.SimpleInterfaceMonitor(
|
|
||||||
respawn_interval=ovsdb_monitor_respawn_interval,
|
|
||||||
ovsdb_connection=cfg.CONF.OVS.ovsdb_connection)
|
|
||||||
|
|
||||||
def start(self):
|
|
||||||
self._monitor.start(block=True)
|
|
||||||
|
|
||||||
def stop(self):
|
|
||||||
try:
|
|
||||||
self._monitor.stop()
|
|
||||||
except async_process.AsyncProcessException:
|
|
||||||
LOG.debug("InterfacePollingMinimizer was not running when stopped")
|
|
||||||
|
|
||||||
def _is_polling_required(self):
|
|
||||||
# Maximize the chances of update detection having a chance to
|
|
||||||
# collect output.
|
|
||||||
eventlet.sleep()
|
|
||||||
return self._monitor.has_updates
|
|
||||||
|
|
||||||
def get_events(self):
|
|
||||||
return self._monitor.get_events()
|
|
|
@ -1,30 +0,0 @@
|
||||||
# Copyright 2015 Cloudbase Solutions.
|
|
||||||
# All Rights Reserved.
|
|
||||||
#
|
|
||||||
# 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.agent.common import base_polling
|
|
||||||
|
|
||||||
|
|
||||||
@contextlib.contextmanager
|
|
||||||
def get_polling_manager(minimize_polling, ovsdb_monitor_respawn_interval):
|
|
||||||
pm = base_polling.AlwaysPoll()
|
|
||||||
yield pm
|
|
||||||
|
|
||||||
|
|
||||||
# TODO(atuvenie): make this manager inherit from
|
|
||||||
# that fully fledged polling manager interface
|
|
||||||
class InterfacePollingMinimizer(object):
|
|
||||||
pass
|
|
|
@ -24,9 +24,9 @@ from oslo_config import cfg
|
||||||
from oslo_utils import uuidutils
|
from oslo_utils import uuidutils
|
||||||
|
|
||||||
from neutron.agent.common import ovs_lib
|
from neutron.agent.common import ovs_lib
|
||||||
|
from neutron.agent.common import polling
|
||||||
from neutron.agent.l2 import l2_agent_extensions_manager as ext_manager
|
from neutron.agent.l2 import l2_agent_extensions_manager as ext_manager
|
||||||
from neutron.agent.linux import interface
|
from neutron.agent.linux import interface
|
||||||
from neutron.agent.linux import polling
|
|
||||||
from neutron.common import utils
|
from neutron.common import utils
|
||||||
from neutron.conf.agent import common as agent_config
|
from neutron.conf.agent import common as agent_config
|
||||||
from neutron.conf import common as common_config
|
from neutron.conf import common as common_config
|
||||||
|
|
|
@ -14,7 +14,9 @@
|
||||||
|
|
||||||
import mock
|
import mock
|
||||||
|
|
||||||
from neutron.agent.common import base_polling as polling
|
from neutron.agent.common import base_polling
|
||||||
|
from neutron.agent.common import polling
|
||||||
|
from neutron.agent.ovsdb.native import helpers
|
||||||
from neutron.tests import base
|
from neutron.tests import base
|
||||||
|
|
||||||
|
|
||||||
|
@ -22,7 +24,7 @@ class TestBasePollingManager(base.BaseTestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(TestBasePollingManager, self).setUp()
|
super(TestBasePollingManager, self).setUp()
|
||||||
self.pm = polling.BasePollingManager()
|
self.pm = base_polling.BasePollingManager()
|
||||||
|
|
||||||
def test__is_polling_required_should_not_be_implemented(self):
|
def test__is_polling_required_should_not_be_implemented(self):
|
||||||
self.assertRaises(NotImplementedError, self.pm._is_polling_required)
|
self.assertRaises(NotImplementedError, self.pm._is_polling_required)
|
||||||
|
@ -65,5 +67,56 @@ class TestBasePollingManager(base.BaseTestCase):
|
||||||
class TestAlwaysPoll(base.BaseTestCase):
|
class TestAlwaysPoll(base.BaseTestCase):
|
||||||
|
|
||||||
def test_is_polling_required_always_returns_true(self):
|
def test_is_polling_required_always_returns_true(self):
|
||||||
pm = polling.AlwaysPoll()
|
pm = base_polling.AlwaysPoll()
|
||||||
self.assertTrue(pm.is_polling_required)
|
self.assertTrue(pm.is_polling_required)
|
||||||
|
|
||||||
|
|
||||||
|
class TestGetPollingManager(base.BaseTestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
super(TestGetPollingManager, self).setUp()
|
||||||
|
mock.patch.object(helpers, 'enable_connection_uri').start()
|
||||||
|
|
||||||
|
def test_return_always_poll_by_default(self):
|
||||||
|
with polling.get_polling_manager() as pm:
|
||||||
|
self.assertEqual(pm.__class__, base_polling.AlwaysPoll)
|
||||||
|
|
||||||
|
def test_manage_polling_minimizer(self):
|
||||||
|
mock_target = 'neutron.agent.common.polling.InterfacePollingMinimizer'
|
||||||
|
with mock.patch('%s.start' % mock_target) as mock_start:
|
||||||
|
with mock.patch('%s.stop' % mock_target) as mock_stop:
|
||||||
|
with polling.get_polling_manager(minimize_polling=True) as pm:
|
||||||
|
self.assertEqual(pm.__class__,
|
||||||
|
polling.InterfacePollingMinimizer)
|
||||||
|
mock_stop.assert_has_calls([mock.call()])
|
||||||
|
mock_start.assert_has_calls([mock.call()])
|
||||||
|
|
||||||
|
|
||||||
|
class TestInterfacePollingMinimizer(base.BaseTestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
super(TestInterfacePollingMinimizer, self).setUp()
|
||||||
|
mock.patch.object(helpers, 'enable_connection_uri').start()
|
||||||
|
self.pm = polling.InterfacePollingMinimizer()
|
||||||
|
|
||||||
|
def test_start_calls_monitor_start(self):
|
||||||
|
with mock.patch.object(self.pm._monitor, 'start') as mock_start:
|
||||||
|
self.pm.start()
|
||||||
|
mock_start.assert_called_with(block=True)
|
||||||
|
|
||||||
|
def test_stop_calls_monitor_stop(self):
|
||||||
|
with mock.patch.object(self.pm._monitor, 'stop') as mock_stop:
|
||||||
|
self.pm.stop()
|
||||||
|
mock_stop.assert_called_with()
|
||||||
|
|
||||||
|
def mock_has_updates(self, return_value):
|
||||||
|
target = ('neutron.agent.common.ovsdb_monitor.SimpleInterfaceMonitor'
|
||||||
|
'.has_updates')
|
||||||
|
return mock.patch(
|
||||||
|
target,
|
||||||
|
new_callable=mock.PropertyMock(return_value=return_value),
|
||||||
|
)
|
||||||
|
|
||||||
|
def test__is_polling_required_returns_when_updates_are_present(self):
|
||||||
|
with self.mock_has_updates(True):
|
||||||
|
self.assertTrue(self.pm._is_polling_required())
|
||||||
|
|
|
@ -1,71 +0,0 @@
|
||||||
# Copyright 2013 Red Hat, Inc.
|
|
||||||
#
|
|
||||||
# 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 mock
|
|
||||||
|
|
||||||
from neutron.agent.common import base_polling
|
|
||||||
from neutron.agent.linux import polling
|
|
||||||
from neutron.agent.ovsdb.native import helpers
|
|
||||||
from neutron.tests import base
|
|
||||||
|
|
||||||
|
|
||||||
class TestGetPollingManager(base.BaseTestCase):
|
|
||||||
|
|
||||||
def setUp(self):
|
|
||||||
super(TestGetPollingManager, self).setUp()
|
|
||||||
mock.patch.object(helpers, 'enable_connection_uri').start()
|
|
||||||
|
|
||||||
def test_return_always_poll_by_default(self):
|
|
||||||
with polling.get_polling_manager() as pm:
|
|
||||||
self.assertEqual(pm.__class__, base_polling.AlwaysPoll)
|
|
||||||
|
|
||||||
def test_manage_polling_minimizer(self):
|
|
||||||
mock_target = 'neutron.agent.linux.polling.InterfacePollingMinimizer'
|
|
||||||
with mock.patch('%s.start' % mock_target) as mock_start:
|
|
||||||
with mock.patch('%s.stop' % mock_target) as mock_stop:
|
|
||||||
with polling.get_polling_manager(minimize_polling=True) as pm:
|
|
||||||
self.assertEqual(pm.__class__,
|
|
||||||
polling.InterfacePollingMinimizer)
|
|
||||||
mock_stop.assert_has_calls([mock.call()])
|
|
||||||
mock_start.assert_has_calls([mock.call()])
|
|
||||||
|
|
||||||
|
|
||||||
class TestInterfacePollingMinimizer(base.BaseTestCase):
|
|
||||||
|
|
||||||
def setUp(self):
|
|
||||||
super(TestInterfacePollingMinimizer, self).setUp()
|
|
||||||
mock.patch.object(helpers, 'enable_connection_uri').start()
|
|
||||||
self.pm = polling.InterfacePollingMinimizer()
|
|
||||||
|
|
||||||
def test_start_calls_monitor_start(self):
|
|
||||||
with mock.patch.object(self.pm._monitor, 'start') as mock_start:
|
|
||||||
self.pm.start()
|
|
||||||
mock_start.assert_called_with(block=True)
|
|
||||||
|
|
||||||
def test_stop_calls_monitor_stop(self):
|
|
||||||
with mock.patch.object(self.pm._monitor, 'stop') as mock_stop:
|
|
||||||
self.pm.stop()
|
|
||||||
mock_stop.assert_called_with()
|
|
||||||
|
|
||||||
def mock_has_updates(self, return_value):
|
|
||||||
target = ('neutron.agent.common.ovsdb_monitor.SimpleInterfaceMonitor'
|
|
||||||
'.has_updates')
|
|
||||||
return mock.patch(
|
|
||||||
target,
|
|
||||||
new_callable=mock.PropertyMock(return_value=return_value),
|
|
||||||
)
|
|
||||||
|
|
||||||
def test__is_polling_required_returns_when_updates_are_present(self):
|
|
||||||
with self.mock_has_updates(True):
|
|
||||||
self.assertTrue(self.pm._is_polling_required())
|
|
Loading…
Reference in New Issue