Merge "Windows OVS: minimize polling"

This commit is contained in:
Zuul 2018-09-05 09:02:27 +00:00 committed by Gerrit Code Review
commit d6f6ddea38
6 changed files with 114 additions and 186 deletions

View File

@ -13,13 +13,63 @@
# License for the specific language governing permissions and limitations
# 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':
from neutron.agent.windows import polling
else:
from neutron.agent.linux import polling
@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()
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()

View File

@ -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()

View File

@ -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

View File

@ -24,9 +24,9 @@ from oslo_config import cfg
from oslo_utils import uuidutils
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.linux import interface
from neutron.agent.linux import polling
from neutron.common import utils
from neutron.conf.agent import common as agent_config
from neutron.conf import common as common_config

View File

@ -14,7 +14,9 @@
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
@ -22,7 +24,7 @@ class TestBasePollingManager(base.BaseTestCase):
def setUp(self):
super(TestBasePollingManager, self).setUp()
self.pm = polling.BasePollingManager()
self.pm = base_polling.BasePollingManager()
def test__is_polling_required_should_not_be_implemented(self):
self.assertRaises(NotImplementedError, self.pm._is_polling_required)
@ -65,5 +67,56 @@ class TestBasePollingManager(base.BaseTestCase):
class TestAlwaysPoll(base.BaseTestCase):
def test_is_polling_required_always_returns_true(self):
pm = polling.AlwaysPoll()
pm = base_polling.AlwaysPoll()
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())

View File

@ -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())