Use write connection for get_vpn_services_on_host
The OVN IPSEC implementation requires write connection. And it will raise errors when try to bind routers with `Can't upgrade a READER transaction to a WRITER mid-transaction`. This alias both to write transation declear so no above error will raise. Closes-Bug: 2100911 Change-Id: I1f5ddbaae7b9a45382ee1307c13f26d346b03644
This commit is contained in:
@@ -71,7 +71,7 @@ class IPsecVpnDriverCallBack:
|
||||
self.driver.name)
|
||||
return query
|
||||
|
||||
@db_api.CONTEXT_READER
|
||||
@db_api.CONTEXT_WRITER
|
||||
def get_vpn_services_on_host(self, context, host=None):
|
||||
"""Returns the vpnservices on the host."""
|
||||
vpnservices = self._get_agent_hosting_vpn_services(
|
||||
|
||||
@@ -24,6 +24,7 @@ from neutron.tests.unit.api import test_extensions
|
||||
from neutron.tests.unit.extensions import test_l3
|
||||
from neutron.tests.unit import testlib_api
|
||||
from neutron_lib import context
|
||||
from neutron_lib.db import api as db_api
|
||||
from neutron_lib import exceptions as n_exc
|
||||
from neutron_lib.plugins import constants as plugin_constants
|
||||
from neutron_lib.plugins import directory
|
||||
@@ -330,6 +331,46 @@ class VPNAgentSchedulerTestCase(VPNAgentSchedulerTestCaseBase):
|
||||
self.assertEqual(VPN_HOSTA, host_before)
|
||||
self.assertEqual(VPN_HOSTB, host_after)
|
||||
|
||||
def test_router_reschedule_with_write_db_wrap(self):
|
||||
self._register_agent_states()
|
||||
agent_a = self.service_plugin.get_vpn_agent_on_host(
|
||||
self.adminContext, VPN_HOSTA)
|
||||
|
||||
with self.vpnservice() as service:
|
||||
# schedule the vpn routers to agent A
|
||||
with db_api.CONTEXT_WRITER.using(self.adminContext):
|
||||
self.service_plugin.auto_schedule_routers(
|
||||
self.adminContext, agent_a)
|
||||
ctxt_mock = mock.MagicMock()
|
||||
call_mock = mock.MagicMock(
|
||||
side_effect=[oslo_messaging.MessagingTimeout, None])
|
||||
ctxt_mock.call = call_mock
|
||||
self.client_mock.prepare = mock.MagicMock(return_value=ctxt_mock)
|
||||
self._take_down_agent_and_run_reschedule(VPN_HOSTA)
|
||||
self.assertEqual(2, call_mock.call_count)
|
||||
# make sure vpn service was rescheduled even when first attempt
|
||||
# failed to notify VPN agent
|
||||
router_id = service['vpnservice']['router_id']
|
||||
host = self._get_agent_host_by_router(router_id)
|
||||
|
||||
vpn_agents = self._list_vpn_agents_hosting_router(router_id)
|
||||
self.assertEqual(1, len(vpn_agents['agents']))
|
||||
self.assertEqual(VPN_HOSTB, host)
|
||||
|
||||
def test_router_reschedule_with_read_db_wrap(self):
|
||||
self._register_agent_states()
|
||||
agent_a = self.service_plugin.get_vpn_agent_on_host(
|
||||
self.adminContext, VPN_HOSTA)
|
||||
|
||||
with self.vpnservice():
|
||||
# schedule the vpn routers to agent A
|
||||
with db_api.CONTEXT_READER.using(self.adminContext):
|
||||
self.assertRaises(
|
||||
TypeError,
|
||||
self.service_plugin.auto_schedule_routers,
|
||||
self.adminContext,
|
||||
agent_a)
|
||||
|
||||
def test_router_reschedule_succeeded_after_failed_notification(self):
|
||||
self._register_agent_states()
|
||||
agent_a = self.service_plugin.get_vpn_agent_on_host(
|
||||
|
||||
@@ -130,9 +130,12 @@ class TestOvnIPsecDriver(base.BaseTestCase):
|
||||
router_id=FAKE_ROUTER_ID,
|
||||
router=self._fake_router
|
||||
)
|
||||
self.svc_plugin.get_vpn_agent_on_host.return_value = {'id': FAKE_HOST}
|
||||
self.svc_plugin.get_vpnservice.return_value = FAKE_VPNSERVICE_1
|
||||
self.svc_plugin.get_vpnservice_router_id.return_value = FAKE_ROUTER_ID
|
||||
self.driver = ipsec_driver.IPsecOvnVPNDriver(self.svc_plugin)
|
||||
self.driver.make_vpnservice_dict = mock.Mock(
|
||||
return_value={'id': FAKE_HOST})
|
||||
self.validator = ipsec_validator.IpsecVpnValidator(self.driver)
|
||||
self.context = n_ctx.get_admin_context()
|
||||
|
||||
@@ -304,3 +307,51 @@ class TestOvnIPsecDriver(base.BaseTestCase):
|
||||
[FAKE_VPN_CONNECTION_1],
|
||||
expected_add, expected_remove
|
||||
)
|
||||
|
||||
|
||||
class TestOvnIPsecCallBackDriver(base.BaseTestCase):
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
vpn_agent = {'host': FAKE_HOST}
|
||||
self.core_plugin = mock.Mock()
|
||||
self.core_plugin.get_vpn_agents_hosting_routers.return_value = \
|
||||
[vpn_agent]
|
||||
|
||||
directory.add_plugin(constants.CORE, self.core_plugin)
|
||||
self._fake_router = FakeSqlQueryObject(
|
||||
id=FAKE_ROUTER_ID,
|
||||
gw_port=FakeSqlQueryObject(network_id=_uuid())
|
||||
)
|
||||
self.svc_plugin = mock.Mock()
|
||||
self.svc_plugin.get_vpn_agents_hosting_routers.return_value = \
|
||||
[vpn_agent]
|
||||
self.svc_plugin.schedule_router.return_value = vpn_agent
|
||||
self.svc_plugin._get_vpnservice.return_value = FakeSqlQueryObject(
|
||||
router_id=FAKE_ROUTER_ID,
|
||||
router=self._fake_router
|
||||
)
|
||||
self.svc_plugin.get_vpn_agent_on_host.return_value = {'id': FAKE_HOST}
|
||||
self.svc_plugin.get_vpnservice.return_value = FAKE_VPNSERVICE_1
|
||||
self.svc_plugin.get_vpnservice_router_id.return_value = FAKE_ROUTER_ID
|
||||
self.driver = ipsec_driver.IPsecOvnVPNDriver(self.svc_plugin)
|
||||
self.driver.make_vpnservice_dict = mock.Mock(
|
||||
return_value={'id': FAKE_HOST})
|
||||
|
||||
def test_get_vpn_services_on_host(self):
|
||||
with mock.patch('neutron_lib.context.get_admin_context') as get_ctx:
|
||||
mock_ctx = mock.Mock()
|
||||
mock_ctx.session.query().join().join().filter.return_value = [
|
||||
{'id': FAKE_HOST}]
|
||||
get_ctx.return_value = mock_ctx
|
||||
context = n_ctx.get_admin_context()
|
||||
driver_callback = ipsec_driver.IPsecVpnOvnDriverCallBack(
|
||||
self.driver)
|
||||
self.assertEqual(
|
||||
[{'id': FAKE_HOST}],
|
||||
driver_callback.get_vpn_services_on_host(
|
||||
context, FAKE_HOST)
|
||||
)
|
||||
self.svc_plugin.get_vpn_agent_on_host.assert_called_once_with(
|
||||
mock.ANY, FAKE_HOST)
|
||||
self.svc_plugin.auto_schedule_routers.assert_called_once_with(
|
||||
mock.ANY, {'id': FAKE_HOST})
|
||||
|
||||
Reference in New Issue
Block a user