From b0b5431d9c5ed4548bb889ebdfd7ffed2b86a66c Mon Sep 17 00:00:00 2001 From: vikas Date: Tue, 15 Mar 2016 03:55:39 -0700 Subject: [PATCH] create Vxlan tunnels from ESXi compute node networking-vsphere, which works for ESXi nodes does not support l2 population. so choosing ovs-vapp agent instead of ovs agent to create tunnel by tunnel sync call, while creating l2-gateway-connection. Closes-Bug: 1544112 Change-Id: I801e539ccc4f9bdce3b829189c97c53ba84a8f48 --- .../services/l2gateway/common/tunnel_calls.py | 51 ++++++++++++ .../services/l2gateway/exceptions.py | 10 +-- .../services/l2gateway/ovsdb/data.py | 82 +++++++++++++------ .../l2gateway/service_drivers/rpc_l2gw.py | 31 +++---- .../l2gateway/common/test_tunnel_calls.py | 62 ++++++++++++++ .../services/l2gateway/ovsdb/test_data.py | 43 +++++++++- .../service_drivers/test_rpc_l2gw.py | 21 ++--- .../unit/services/l2gateway/test_plugin.py | 2 - 8 files changed, 242 insertions(+), 60 deletions(-) create mode 100644 networking_l2gw/services/l2gateway/common/tunnel_calls.py create mode 100644 networking_l2gw/tests/unit/services/l2gateway/common/test_tunnel_calls.py diff --git a/networking_l2gw/services/l2gateway/common/tunnel_calls.py b/networking_l2gw/services/l2gateway/common/tunnel_calls.py new file mode 100644 index 00000000..5803e106 --- /dev/null +++ b/networking_l2gw/services/l2gateway/common/tunnel_calls.py @@ -0,0 +1,51 @@ +# Copyright (c) 2016 OpenStack Foundation +# +# 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. + +from neutron.common import topics as neutron_topics +from neutron.plugins.ml2.drivers.l2pop import rpc as l2pop_rpc +from neutron.plugins.ml2 import managers +from neutron.plugins.ml2 import rpc as rpc + + +class Tunnel_Calls(object): + """Common tunnel calls for L2 agent.""" + def __init__(self): + self._construct_rpc_stuff() + + def _construct_rpc_stuff(self): + self.notifier = rpc.AgentNotifierApi(neutron_topics.AGENT) + self.type_manager = managers.TypeManager() + self.tunnel_rpc_obj = rpc.RpcCallbacks(self.notifier, + self.type_manager) + + def trigger_tunnel_sync(self, context, tunnel_ip): + """Sends tunnel sync RPC message to the neutron + + L2 agent. + """ + tunnel_dict = {'tunnel_ip': tunnel_ip, + 'tunnel_type': 'vxlan'} + self.tunnel_rpc_obj.tunnel_sync(context, + **tunnel_dict) + + def trigger_l2pop_sync(self, context, other_fdb_entries): + """Sends L2pop ADD RPC message to the neutron L2 agent.""" + l2pop_rpc.L2populationAgentNotifyAPI( + ).add_fdb_entries(context, other_fdb_entries) + + def trigger_l2pop_delete(self, context, other_fdb_entries, host=None): + """Sends L2pop DELETE RPC message to the neutron L2 agent.""" + l2pop_rpc.L2populationAgentNotifyAPI( + ).remove_fdb_entries(context, other_fdb_entries, host) diff --git a/networking_l2gw/services/l2gateway/exceptions.py b/networking_l2gw/services/l2gateway/exceptions.py index dccdfcac..bbf9adce 100644 --- a/networking_l2gw/services/l2gateway/exceptions.py +++ b/networking_l2gw/services/l2gateway/exceptions.py @@ -28,15 +28,15 @@ class L2GatewayNotFound(exceptions.NotFound): message = _("L2 Gateway %(gateway_id)s could not be found") -class OvsAgentNotFound(exceptions.NotFound): - message = _("ovs agent not found in host %(host)s") - - class L2GatewayDeviceInUse(exceptions.InUse): message = _("L2 Gateway Device '%(device_id)s' is still used by " "one or more network gateways.") +class L2AgentNotFoundByHost(exceptions.NotFound): + message = _("L2 Agent for host '%(host)s' could not be found.") + + class L2GatewayDeviceNotFound(exceptions.NotFound): message = _("L2 Gateway Device %(device_id)s could not be found.") @@ -129,5 +129,5 @@ base.FAULT_MAP.update({L2GatewayInUse: web_exc.HTTPConflict, L2GatewaySegmentationRequired: web_exc.HTTPConflict, L2MultipleGatewayConnections: web_exc.HTTPConflict, L2GatewayDuplicateSegmentationID: web_exc.HTTPConflict, - OvsAgentNotFound: web_exc.HTTPNotFound, + L2AgentNotFoundByHost: web_exc.HTTPNotFound, OVSDBError: web_exc.HTTPConflict}) diff --git a/networking_l2gw/services/l2gateway/ovsdb/data.py b/networking_l2gw/services/l2gateway/ovsdb/data.py index c98935f8..bff9c111 100644 --- a/networking_l2gw/services/l2gateway/ovsdb/data.py +++ b/networking_l2gw/services/l2gateway/ovsdb/data.py @@ -13,8 +13,8 @@ # See the License for the specific language governing permissions and # limitations under the License. +from neutron.extensions import portbindings from neutron import manager -from neutron.plugins.ml2.drivers.l2pop import rpc as l2pop_rpc from networking_l2gw._i18n import _LE from networking_l2gw.db.l2gateway import l2gateway_db @@ -22,6 +22,7 @@ from networking_l2gw.db.l2gateway.ovsdb import lib as db from networking_l2gw.services.l2gateway.common import constants as n_const from networking_l2gw.services.l2gateway.common import ovsdb_schema from networking_l2gw.services.l2gateway.common import topics +from networking_l2gw.services.l2gateway.common import tunnel_calls from networking_l2gw.services.l2gateway import exceptions as l2gw_exc from networking_l2gw.services.l2gateway.service_drivers import agent_api @@ -70,6 +71,8 @@ class OVSDBData(object): self.agent_rpc = agent_api.L2gatewayAgentApi( topics.L2GATEWAY_AGENT, cfg.CONF.host) self.l2gw_mixin = l2gateway_db.L2GatewayMixin() + self.core_plugin = manager.NeutronManager.get_plugin() + self.tunnel_call = tunnel_calls.Tunnel_Calls() def update_ovsdb_changes(self, context, ovsdb_data): """RPC to update the changes from OVSDB in the database.""" @@ -266,13 +269,55 @@ class OVSDBData(object): physical_switch_ips.add(physical_switch.get('tunnel_ip')) return list(physical_switch_ips) + def _get_agent_by_mac(self, context, mac): + host = None + mac_addr = mac.get('mac') + port = self._get_port_by_mac(context, mac_addr) + for port_dict in port: + host = port_dict[portbindings.HOST_ID] + agent_l2_pop_enabled = self._get_agent_details_by_host(context, host) + return agent_l2_pop_enabled + + def _get_port_by_mac(self, context, mac_addr): + port = self.core_plugin.get_ports( + context, filters={'mac_address': [mac_addr]}) + return port + + def _get_agent_details_by_host(self, context, host): + l2_agent = None + agent_l2_pop_enabled = None + agents = self.core_plugin.get_agents( + context, filters={'host': [host]}) + for agent in agents: + agent_tunnel_type = agent['configurations'].get('tunnel_types', []) + agent_l2_pop_enabled = agent['configurations'].get('l2_population', + None) + if n_const.VXLAN in agent_tunnel_type: + l2_agent = agent + break + if not l2_agent: + raise l2gw_exc.L2AgentNotFoundByHost( + host=host) + return agent_l2_pop_enabled + def _handle_l2pop(self, context, new_remote_macs): + """handle vxlan tunnel creation based on whether l2pop is enabled or not. + + if l2pop is enabled in L2 agent on a host to which port belongs, then + call add_fdb_entries. otherwise, call tunnel_sync. + """ for mac in new_remote_macs: - agent_ips = self._get_physical_switch_ips(context, mac) - for agent_ip in agent_ips: + agent_l2_pop_enabled = self._get_agent_by_mac(context, mac) + physical_switches = self._get_physical_switch_ips(context, mac) + for physical_switch in physical_switches: other_fdb_entries = self._get_fdb_entries( - context, agent_ip, mac.get('logical_switch_id')) - self._trigger_l2pop_sync(context, other_fdb_entries) + context, physical_switch, mac.get('logical_switch_id')) + if agent_l2_pop_enabled: + self.tunnel_call.trigger_l2pop_sync(context, + other_fdb_entries) + else: + self.tunnel_call.trigger_tunnel_sync(context, + physical_switch) def _process_modified_physical_ports(self, context, @@ -418,13 +463,13 @@ class OVSDBData(object): other_fdb_entries = self._get_fdb_entries( context, physical_switch_ip, logical_switch_id) agent_host = tunneling_ip_dict.get(agent_ip) - self._trigger_l2pop_delete( + self.tunnel_call.trigger_l2pop_delete( context, other_fdb_entries, agent_host) else: for logical_switch_id in logical_switch_ids: other_fdb_entries = self._get_fdb_entries( context, agent_ip, logical_switch_id) - self._trigger_l2pop_delete( + self.tunnel_call.trigger_l2pop_delete( context, other_fdb_entries) db.delete_physical_locator(context, pl_dict) @@ -454,13 +499,14 @@ class OVSDBData(object): def _get_agent_ips(self, context): agent_ip_dict = {} - ml2plugin = manager.NeutronManager.get_plugin() - agents = ml2plugin.get_agents( - context, filters={'agent_type': [constants.AGENT_TYPE_OVS]}) + agents = self.core_plugin.get_agents( + context) for agent in agents: - conf_dict = agent.get('configurations') - tunnel_ip = conf_dict.get('tunneling_ip') - agent_ip_dict[tunnel_ip] = agent.get('host') + conf_dict_tunnel_type = agent['configurations'].get( + "tunnel_types", []) + if n_const.VXLAN in conf_dict_tunnel_type: + tunnel_ip = agent['configurations'].get('tunneling_ip') + agent_ip_dict[tunnel_ip] = agent.get('host') return agent_ip_dict def _get_fdb_entries(self, context, agent_ip, logical_switch_uuid): @@ -476,13 +522,3 @@ class OVSDBData(object): [port_fdb_entries] }}} return other_fdb_entries - - def _trigger_l2pop_sync(self, context, other_fdb_entries): - """Sends L2pop ADD RPC message to the neutron L2 agent.""" - l2pop_rpc.L2populationAgentNotifyAPI( - ).add_fdb_entries(context, other_fdb_entries) - - def _trigger_l2pop_delete(self, context, other_fdb_entries, host=None): - """Sends L2pop DELETE RPC message to the neutron L2 agent.""" - l2pop_rpc.L2populationAgentNotifyAPI( - ).remove_fdb_entries(context, other_fdb_entries, host) diff --git a/networking_l2gw/services/l2gateway/service_drivers/rpc_l2gw.py b/networking_l2gw/services/l2gateway/service_drivers/rpc_l2gw.py index b4a91427..a32a8603 100644 --- a/networking_l2gw/services/l2gateway/service_drivers/rpc_l2gw.py +++ b/networking_l2gw/services/l2gateway/service_drivers/rpc_l2gw.py @@ -30,7 +30,6 @@ from networking_l2gw.services.l2gateway import exceptions as l2gw_exc from networking_l2gw.services.l2gateway import service_drivers from networking_l2gw.services.l2gateway.service_drivers import agent_api -from neutron_lib import constants as n_const from neutron_lib import exceptions from oslo_config import cfg from oslo_log import log as logging @@ -473,14 +472,11 @@ class L2gwRpcDriver(service_drivers.L2gwDriver): def _get_ip_details(self, context, port): host = port[portbindings.HOST_ID] agent = self._get_agent_details(context, host) - if agent: - conf_dict = agent[0].get("configurations") - dst_ip = conf_dict.get("tunneling_ip") - fixed_ip_list = port.get('fixed_ips') - fixed_ip_list = fixed_ip_list[0] - return dst_ip, fixed_ip_list.get('ip_address') - else: - raise l2gw_exc.OvsAgentNotFound(host=host) + conf_dict = agent.get("configurations") + dst_ip = conf_dict.get("tunneling_ip") + fixed_ip_list = port.get('fixed_ips') + fixed_ip_list = fixed_ip_list[0] + return dst_ip, fixed_ip_list.get('ip_address') def _get_network_details(self, context, network_id): network = self.service_plugin._core_plugin.get_network(context, @@ -493,11 +489,18 @@ class L2gwRpcDriver(service_drivers.L2gwDriver): return ports def _get_agent_details(self, context, host): - agent = self.service_plugin._core_plugin.get_agents( - context, - filters={'agent_type': [n_const.AGENT_TYPE_OVS], - 'host': [host]}) - return agent + l2_agent = None + agents = self.service_plugin._core_plugin.get_agents( + context, filters={'host': [host]}) + for agent in agents: + agent_tunnel_type = agent['configurations'].get('tunnel_types', []) + if constants.VXLAN in agent_tunnel_type: + l2_agent = agent + break + if not l2_agent: + raise l2gw_exc.L2AgentNotFoundByHost( + host=host) + return l2_agent def _get_logical_switch_dict(self, context, logical_switch, gw_connection): if logical_switch: diff --git a/networking_l2gw/tests/unit/services/l2gateway/common/test_tunnel_calls.py b/networking_l2gw/tests/unit/services/l2gateway/common/test_tunnel_calls.py new file mode 100644 index 00000000..756630f6 --- /dev/null +++ b/networking_l2gw/tests/unit/services/l2gateway/common/test_tunnel_calls.py @@ -0,0 +1,62 @@ +# Copyright (c) 2016 OpenStack Foundation +# +# 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 + +import contextlib +from neutron.plugins.ml2.drivers.l2pop import rpc as l2pop_rpc +from neutron.plugins.ml2.drivers import type_tunnel +from neutron.plugins.ml2 import managers +from neutron.plugins.ml2 import rpc as rpc +from neutron.tests import base + +from networking_l2gw.services.l2gateway.common import tunnel_calls + + +class TestTunnelCalls(base.BaseTestCase): + + def setUp(self): + super(TestTunnelCalls, self).setUp() + mock.patch.object(managers, 'TypeManager').start() + self.tunnel_call = tunnel_calls.Tunnel_Calls() + self.context = mock.MagicMock() + + def test_trigger_tunnel_sync(self): + with contextlib.nested( + mock.patch.object(rpc, 'RpcCallbacks'), + mock.patch.object(type_tunnel.TunnelRpcCallbackMixin, + 'tunnel_sync')) as (mock_rpc, mock_tunnel_sync): + self.tunnel_call.trigger_tunnel_sync(self.context, 'fake_ip') + mock_tunnel_sync.assert_called_with( + self.context, tunnel_ip='fake_ip', tunnel_type='vxlan') + + def test_trigger_l2pop_sync(self): + fake_fdb_entry = "fake_fdb_entry" + with mock.patch.object(l2pop_rpc.L2populationAgentNotifyAPI, + 'add_fdb_entries') as (mock_add_fdb): + self.tunnel_call.trigger_l2pop_sync(self.context, + fake_fdb_entry) + mock_add_fdb.assert_called_with(self.context, + fake_fdb_entry) + + def test_trigger_l2pop_delete(self): + fake_fdb_entry = "fake_fdb_entry" + fake_host = 'fake_host' + with mock.patch.object(l2pop_rpc.L2populationAgentNotifyAPI, + 'remove_fdb_entries') as (mock_delete_fdb): + self.tunnel_call.trigger_l2pop_delete(self.context, + fake_fdb_entry, fake_host) + mock_delete_fdb.assert_called_with(self.context, + fake_fdb_entry, fake_host) diff --git a/networking_l2gw/tests/unit/services/l2gateway/ovsdb/test_data.py b/networking_l2gw/tests/unit/services/l2gateway/ovsdb/test_data.py index 9302e921..60505aed 100644 --- a/networking_l2gw/tests/unit/services/l2gateway/ovsdb/test_data.py +++ b/networking_l2gw/tests/unit/services/l2gateway/ovsdb/test_data.py @@ -18,12 +18,14 @@ import mock import contextlib from neutron import context from neutron import manager +from neutron.plugins.ml2 import managers from neutron.tests import base from networking_l2gw.db.l2gateway import l2gateway_db from networking_l2gw.db.l2gateway.ovsdb import lib from networking_l2gw.services.l2gateway.common import constants as n_const from networking_l2gw.services.l2gateway.common import ovsdb_schema +from networking_l2gw.services.l2gateway.common import tunnel_calls from networking_l2gw.services.l2gateway.ovsdb import data from networking_l2gw.services.l2gateway.service_drivers import agent_api @@ -67,6 +69,8 @@ class TestOVSDBData(base.BaseTestCase): super(TestOVSDBData, self).setUp() self.context = context.get_admin_context() self.ovsdb_identifier = 'fake_ovsdb_id' + mock.patch.object(manager.NeutronManager, 'get_plugin').start() + mock.patch.object(managers, 'TypeManager').start() self.ovsdb_data = data.OVSDBData(self.ovsdb_identifier) def test_init(self): @@ -144,7 +148,9 @@ class TestOVSDBData(base.BaseTestCase): mock.patch.object(self.ovsdb_data, '_process_deleted_local_macs'), mock.patch.object(self.ovsdb_data, - '_process_deleted_remote_macs') + '_process_deleted_remote_macs'), + mock.patch.object(self.ovsdb_data, + '_handle_l2pop') ) as (process_new_logical_switches, process_new_physical_ports, process_new_physical_switches, @@ -158,7 +164,8 @@ class TestOVSDBData(base.BaseTestCase): process_deleted_physical_ports, process_deleted_physical_locators, process_deleted_local_macs, - process_deleted_remote_macs): + process_deleted_remote_macs, + mock_handle_l2pop): self.ovsdb_data.entry_table = { 'new_logical_switches': process_new_logical_switches, 'new_physical_ports': process_new_physical_ports, @@ -205,6 +212,7 @@ class TestOVSDBData(base.BaseTestCase): self.context, fake_deleted_local_macs) process_deleted_remote_macs.assert_called_with( self.context, fake_deleted_remote_macs) + self.assertTrue(mock_handle_l2pop.called) def test_notify_ovsdb_states(self): fake_ovsdb_states = {'ovsdb1': 'connected'} @@ -377,6 +385,31 @@ class TestOVSDBData(base.BaseTestCase): 'fake_ovsdb_id') delete_ls.assert_called_with(self.context, fake_dict) + def test_get_agent_by_mac(self): + fake_mac = {'mac': 'fake_mac_1'} + fake_port = [{'binding:host_id': 'fake_host'}] + with contextlib.nested( + mock.patch.object(self.ovsdb_data, '_get_port_by_mac', + return_value=fake_port), + mock.patch.object(self.ovsdb_data, + '_get_agent_details_by_host')) as ( + mock_get_port_mac, mock_get_agent_detail): + self.ovsdb_data._get_agent_by_mac(self.context, fake_mac) + mock_get_port_mac.assert_called_with(self.context, 'fake_mac_1') + mock_get_agent_detail.assert_called_with(self.context, 'fake_host') + + def test_get_agent_details_by_host(self): + fake_agent = {'configurations': {'tunnel_types': ["vxlan"], + 'l2_population': True}} + fake_agents = [fake_agent] + with contextlib.nested( + mock.patch.object(self.ovsdb_data.core_plugin, + 'get_agents', + return_value=fake_agents)): + l2pop_enabled = self.ovsdb_data._get_agent_details_by_host( + self.context, 'fake_host') + self.assertTrue(l2pop_enabled) + def test_process_deleted_physical_switches(self): fake_dict = {} fake_deleted_physical_switches = [fake_dict] @@ -509,7 +542,8 @@ class TestOVSDBData(base.BaseTestCase): 'delete_physical_locator'), mock.patch.object(data.OVSDBData, '_get_agent_ips', return_value={'1.1.1.1': 'hostname'}), - mock.patch.object(data.OVSDBData, '_trigger_l2pop_delete') + mock.patch.object(tunnel_calls.Tunnel_Calls, + 'trigger_l2pop_delete') ) as (get_ls, get_all_ps, get_fdb, delete_pl, get_agent_ips, trig_l2pop): self.ovsdb_data._process_deleted_physical_locators( @@ -547,7 +581,8 @@ class TestOVSDBData(base.BaseTestCase): 'delete_physical_locator'), mock.patch.object(data.OVSDBData, '_get_agent_ips', return_value={'2.2.2.2': 'hostname'}), - mock.patch.object(data.OVSDBData, '_trigger_l2pop_delete') + mock.patch.object(tunnel_calls.Tunnel_Calls, + 'trigger_l2pop_delete') ) as (get_ls, get_all_ps, get_fdb, delete_pl, get_agent_ips, trig_l2pop): self.ovsdb_data._process_deleted_physical_locators( diff --git a/networking_l2gw/tests/unit/services/l2gateway/service_drivers/test_rpc_l2gw.py b/networking_l2gw/tests/unit/services/l2gateway/service_drivers/test_rpc_l2gw.py index 5e16597c..4ada6263 100644 --- a/networking_l2gw/tests/unit/services/l2gateway/service_drivers/test_rpc_l2gw.py +++ b/networking_l2gw/tests/unit/services/l2gateway/service_drivers/test_rpc_l2gw.py @@ -42,7 +42,6 @@ class TestL2gwRpcDriver(base.BaseTestCase): self.plugin = rpc_l2gw.L2gwRpcDriver(self.service_plugin) self.plugin.agent_rpc = mock.MagicMock() self.ovsdb_identifier = 'fake_ovsdb_id' - self.ovsdb_data = data.OVSDBData(self.ovsdb_identifier) self.context = mock.ANY def test_l2rpcdriver_init(self): @@ -262,7 +261,7 @@ class TestL2gwRpcDriver(base.BaseTestCase): def test_get_ip_details(self): fake_port = {'binding:host_id': 'fake_host', 'fixed_ips': [{'ip_address': 'fake_ip'}]} - fake_agent = [{'configurations': {'tunneling_ip': 'fake_tun_ip'}}] + fake_agent = {'configurations': {'tunneling_ip': 'fake_tun_ip'}} with mock.patch.object(self.plugin, '_get_agent_details', return_value=fake_agent) as get_agent: @@ -272,16 +271,14 @@ class TestL2gwRpcDriver(base.BaseTestCase): self.assertEqual(ret_dst_ip, 'fake_tun_ip') self.assertEqual(ret_ip_add, 'fake_ip') - def test_get_ip_details_for_no_ovs_agent(self): - fake_port = {'binding:host_id': 'fake_host', - 'fixed_ips': [{'ip_address': 'fake_ip'}]} - with mock.patch.object(self.plugin, - '_get_agent_details', - return_value=None): - self.assertRaises(l2gw_exc.OvsAgentNotFound, - self.plugin._get_ip_details, - self.context, - fake_port) + def test_get_agent_details_for_no_ovs_agent(self): + core_plugin = mock.PropertyMock() + type(self.service_plugin)._core_plugin = core_plugin + (self.service_plugin._core_plugin.get_agents. + return_value) = [] + self.assertRaises(l2gw_exc.L2AgentNotFoundByHost, + self.plugin._get_agent_details, + self.context, 'fake_host') def test_get_network_details(self): fake_network = {'id': 'fake_network_id', diff --git a/networking_l2gw/tests/unit/services/l2gateway/test_plugin.py b/networking_l2gw/tests/unit/services/l2gateway/test_plugin.py index 74e1a0ee..d83df1b1 100644 --- a/networking_l2gw/tests/unit/services/l2gateway/test_plugin.py +++ b/networking_l2gw/tests/unit/services/l2gateway/test_plugin.py @@ -19,7 +19,6 @@ from neutron.tests import base from networking_l2gw.db.l2gateway import l2gateway_db from networking_l2gw.services.l2gateway.common import config -from networking_l2gw.services.l2gateway.ovsdb import data from networking_l2gw.services.l2gateway import plugin as l2gw_plugin @@ -39,7 +38,6 @@ class TestL2GatewayPlugin(base.BaseTestCase): self.context = mock.MagicMock() self.plugin = l2gw_plugin.L2GatewayPlugin() self.ovsdb_identifier = 'fake_ovsdb_id' - self.ovsdb_data = data.OVSDBData(self.ovsdb_identifier) def _get_fake_l2_gateway(self): fake_l2_gateway_id = "5227c228-6bba-4bbe-bdb8-6942768ff0f1"