1244 lines
40 KiB
Python
1244 lines
40 KiB
Python
# Copyright 2022 Red Hat, Inc.
|
|
# 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.
|
|
|
|
from unittest import mock
|
|
|
|
from oslo_config import cfg
|
|
|
|
from ovn_bgp_agent import config
|
|
from ovn_bgp_agent import constants
|
|
from ovn_bgp_agent.drivers.openstack import ovn_stretched_l2_bgp_driver
|
|
from ovn_bgp_agent.drivers.openstack.utils import frr
|
|
from ovn_bgp_agent.drivers.openstack.utils import ovn
|
|
from ovn_bgp_agent.drivers.openstack.utils import ovs
|
|
from ovn_bgp_agent.tests import base as test_base
|
|
from ovn_bgp_agent.tests.unit import fakes
|
|
from ovn_bgp_agent.utils import linux_net
|
|
|
|
import ipaddress
|
|
|
|
CONF = cfg.CONF
|
|
|
|
|
|
class TestHashedRoute(test_base.TestCase):
|
|
def setUp(self):
|
|
super(TestHashedRoute, self).setUp()
|
|
self.table = set()
|
|
self.route = ovn_stretched_l2_bgp_driver.HashedRoute(
|
|
"192.168.0.0", 24, "192.168.1.1")
|
|
self.invalid_route = ovn_stretched_l2_bgp_driver.HashedRoute(
|
|
"192.168.0.0", 24, "192.168.1.2")
|
|
self.table.add(self.route)
|
|
|
|
def test_lookup(self):
|
|
self.assertTrue(self.route in self.table)
|
|
self.assertFalse(self.invalid_route in self.table)
|
|
|
|
def test_delete(self):
|
|
self.table.remove(self.route)
|
|
self.assertEqual(0, len(self.table))
|
|
|
|
|
|
class TestOVNBGPStretchedL2Driver(test_base.TestCase):
|
|
def setUp(self):
|
|
super(TestOVNBGPStretchedL2Driver, self).setUp()
|
|
config.register_opts()
|
|
CONF.set_override(
|
|
"address_scopes",
|
|
"11111111-1111-1111-1111-11111111,22222222-2222-2222-2222-22222222", # NOQA E501
|
|
)
|
|
self.bgp_driver = ovn_stretched_l2_bgp_driver.OVNBGPStretchedL2Driver()
|
|
self.bgp_driver._post_fork_event = mock.Mock()
|
|
self.bgp_driver.sb_idl = mock.Mock()
|
|
self.sb_idl = self.bgp_driver.sb_idl
|
|
self.bgp_driver.chassis = "fake-chassis"
|
|
# self.bgp_driver.ovn_routing_tables = {self.bridge: 'fake-table'}
|
|
# self.bgp_driver.ovn_bridge_mappings = {'fake-network': self.bridge}
|
|
|
|
self.mock_sbdb = mock.patch.object(ovn, "OvnSbIdl").start()
|
|
self.mock_ovs_idl = mock.patch.object(ovs, "OvsIdl").start()
|
|
self.ipv4 = "192.168.1.17"
|
|
self.ipv6 = "2002::1234:abcd:ffff:c0a8:101"
|
|
self.fip = "172.24.4.33"
|
|
self.mac = "aa:bb:cc:dd:ee:ff"
|
|
self.bgp_driver.ovs_idl = self.mock_ovs_idl
|
|
|
|
self.test_route_ipv4 = ovn_stretched_l2_bgp_driver.HashedRoute(
|
|
network="192.168.1.0",
|
|
prefix_len=24,
|
|
dst="10.0.0.1",
|
|
)
|
|
|
|
self.test_route_ipv6 = ovn_stretched_l2_bgp_driver.HashedRoute(
|
|
network="fdcc:8cf2:d40c:2::",
|
|
prefix_len=64,
|
|
dst="fd51:f4b3:872:eda::1",
|
|
)
|
|
|
|
self.addr_scopev4 = "11111111-1111-1111-1111-11111111"
|
|
self.addr_scopev6 = "22222222-2222-2222-2222-22222222"
|
|
self.addr_scope = {
|
|
constants.IP_VERSION_4: self.addr_scopev4,
|
|
constants.IP_VERSION_6: self.addr_scopev6,
|
|
}
|
|
|
|
self.addr_scope_external_ids = {
|
|
"neutron:subnet_pool_addr_scope4": self.addr_scopev4,
|
|
"neutron:subnet_pool_addr_scope6": self.addr_scopev6,
|
|
}
|
|
|
|
self.cr_lrp0 = mock.Mock()
|
|
self.cr_lrp0.mac = [
|
|
"ff:ff:ff:ff:ff:00 10.0.0.1/24 fd51:f4b3:872:eda::1/64"
|
|
]
|
|
self.cr_lrp0.datapath = "fake-router-dp"
|
|
self.cr_lrp0.type = constants.OVN_CHASSISREDIRECT_VIF_PORT_TYPE
|
|
self.cr_lrp0.logical_port = "cr-lrp-fake-port"
|
|
|
|
self.lp0 = mock.Mock()
|
|
self.lp0.external_ids = self.addr_scope_external_ids
|
|
|
|
self.router_port = fakes.create_object(
|
|
{
|
|
"name": "fake-router-port",
|
|
"mac": [
|
|
"ff:ff:ff:ff:ff:01 192.168.1.1/24 fdcc:8cf2:d40c:2::1/64"
|
|
],
|
|
"logical_port": "lrp-fake-logical-port",
|
|
}
|
|
)
|
|
|
|
self.fake_patch_port = fakes.create_object(
|
|
{
|
|
"name": "fake-patch-port",
|
|
"mac": [
|
|
"ff:ff:ff:ff:ff:01 192.168.1.1/24 fdcc:8cf2:d40c:2::1/64"
|
|
],
|
|
"external_ids": self.addr_scope_external_ids,
|
|
"logical_port": "fake-port",
|
|
}
|
|
)
|
|
|
|
# Mock pyroute2.NDB context manager object
|
|
self.mock_ndb = mock.patch.object(linux_net.pyroute2, "NDB").start()
|
|
self.fake_ndb = self.mock_ndb().__enter__()
|
|
|
|
@mock.patch.object(linux_net, "ensure_ovn_device")
|
|
@mock.patch.object(linux_net, "delete_routes_from_table")
|
|
@mock.patch.object(frr, "vrf_leak")
|
|
def test_start(self, mock_vrf, mock_delete_routes, mock_ensure_ovn_device):
|
|
CONF.set_override("clear_vrf_routes_on_startup", True)
|
|
|
|
self.bgp_driver.start()
|
|
|
|
mock_vrf.assert_called_once_with(
|
|
CONF.bgp_vrf,
|
|
CONF.bgp_AS,
|
|
CONF.bgp_router_id,
|
|
template=frr.LEAK_VRF_KERNEL_TEMPLATE,
|
|
)
|
|
# Assert connections were started
|
|
self.mock_ovs_idl().start.assert_called_once_with(
|
|
CONF.ovsdb_connection
|
|
)
|
|
self.mock_sbdb().start.assert_called_once_with()
|
|
mock_delete_routes.assert_called_once_with(CONF.bgp_vrf_table_id)
|
|
mock_ensure_ovn_device.assert_called_once_with(
|
|
CONF.bgp_nic, CONF.bgp_vrf)
|
|
|
|
@mock.patch.object(linux_net, "ensure_ovn_device")
|
|
@mock.patch.object(linux_net, "delete_routes_from_table")
|
|
@mock.patch.object(frr, "vrf_leak")
|
|
def test_start_clear_routes(
|
|
self, mock_vrf, mock_delete_routes, mock_ensure_ovn_device):
|
|
CONF.set_override("clear_vrf_routes_on_startup", False)
|
|
|
|
self.bgp_driver.start()
|
|
|
|
mock_vrf.assert_called_once_with(
|
|
CONF.bgp_vrf,
|
|
CONF.bgp_AS,
|
|
CONF.bgp_router_id,
|
|
template=frr.LEAK_VRF_KERNEL_TEMPLATE,
|
|
)
|
|
# Assert connections were started
|
|
self.mock_ovs_idl().start.assert_called_once_with(
|
|
CONF.ovsdb_connection
|
|
)
|
|
self.mock_sbdb().start.assert_called_once_with()
|
|
mock_delete_routes.assert_not_called()
|
|
mock_ensure_ovn_device.assert_called_once_with(
|
|
CONF.bgp_nic, CONF.bgp_vrf)
|
|
|
|
@mock.patch.object(linux_net, "add_ip_route")
|
|
def test__add_route(self, mock_add_route):
|
|
for test_route in [self.test_route_ipv4, self.test_route_ipv6]:
|
|
self.bgp_driver._add_route(
|
|
test_route.network,
|
|
test_route.prefix_len,
|
|
test_route.dst,
|
|
)
|
|
|
|
mock_add_route.assert_called_with(
|
|
mock.ANY,
|
|
test_route.network,
|
|
CONF.bgp_vrf_table_id,
|
|
CONF.bgp_nic,
|
|
vlan=None,
|
|
mask=test_route.prefix_len,
|
|
via=test_route.dst,
|
|
)
|
|
|
|
self.assertTrue(test_route in self.bgp_driver.vrf_routes)
|
|
|
|
@mock.patch.object(linux_net, "del_ip_route")
|
|
def test__del_route(self, mock_del_route):
|
|
self.bgp_driver.vrf_routes.add(self.test_route_ipv4)
|
|
self.bgp_driver.vrf_routes.add(self.test_route_ipv6)
|
|
for test_route in [self.test_route_ipv4, self.test_route_ipv6]:
|
|
self.bgp_driver._del_route(
|
|
test_route.network,
|
|
test_route.prefix_len,
|
|
test_route.dst,
|
|
)
|
|
|
|
mock_del_route.assert_called_with(
|
|
mock.ANY,
|
|
test_route.network,
|
|
CONF.bgp_vrf_table_id,
|
|
CONF.bgp_nic,
|
|
vlan=None,
|
|
mask=test_route.prefix_len,
|
|
via=test_route.dst,
|
|
)
|
|
|
|
self.assertTrue(test_route not in self.bgp_driver.vrf_routes)
|
|
|
|
def test__get_addr_scopes(self):
|
|
addr_scopes = self.bgp_driver._get_addr_scopes(self.lp0)
|
|
self.assertEqual(self.addr_scope, addr_scopes)
|
|
|
|
def test__address_scope_allowed(self):
|
|
test_scope2 = {
|
|
constants.IP_VERSION_4: self.addr_scopev4,
|
|
constants.IP_VERSION_6: "33333333-3333-3333-3333-33333333",
|
|
}
|
|
|
|
self.assertTrue(
|
|
self.bgp_driver._address_scope_allowed(
|
|
self.addr_scope,
|
|
test_scope2,
|
|
constants.IP_VERSION_4,
|
|
)
|
|
)
|
|
|
|
self.assertFalse(
|
|
self.bgp_driver._address_scope_allowed(
|
|
self.addr_scope,
|
|
test_scope2,
|
|
constants.IP_VERSION_6,
|
|
)
|
|
)
|
|
|
|
def test__address_scope_not_allowed_scope(self):
|
|
test_scope1 = {
|
|
constants.IP_VERSION_4: "33333333-3333-3333-3333-33333333",
|
|
constants.IP_VERSION_6: "33333333-3333-3333-3333-33333333",
|
|
}
|
|
|
|
test_scope2 = {
|
|
constants.IP_VERSION_4: "33333333-3333-3333-3333-33333333",
|
|
constants.IP_VERSION_6: "33333333-3333-3333-3333-33333333",
|
|
}
|
|
|
|
self.assertFalse(
|
|
self.bgp_driver._address_scope_allowed(
|
|
test_scope1,
|
|
test_scope2,
|
|
constants.IP_VERSION_4,
|
|
)
|
|
)
|
|
|
|
self.assertFalse(
|
|
self.bgp_driver._address_scope_allowed(
|
|
test_scope1,
|
|
test_scope2,
|
|
constants.IP_VERSION_6,
|
|
)
|
|
)
|
|
|
|
def test__address_scope_allowed_no_scope(self):
|
|
self.bgp_driver.allowed_address_scopes = set()
|
|
test_scope2 = {
|
|
constants.IP_VERSION_4: None,
|
|
constants.IP_VERSION_6: None,
|
|
}
|
|
|
|
self.assertTrue(
|
|
self.bgp_driver._address_scope_allowed(
|
|
self.addr_scope,
|
|
test_scope2,
|
|
constants.IP_VERSION_4,
|
|
)
|
|
)
|
|
|
|
self.assertTrue(
|
|
self.bgp_driver._address_scope_allowed(
|
|
self.addr_scope,
|
|
test_scope2,
|
|
constants.IP_VERSION_6,
|
|
)
|
|
)
|
|
|
|
def test__address_scope_allowed_no_match(self):
|
|
test_scope2 = {
|
|
constants.IP_VERSION_4: None,
|
|
constants.IP_VERSION_6: "44444444-4444-4444-4444-44444444",
|
|
}
|
|
|
|
self.assertFalse(
|
|
self.bgp_driver._address_scope_allowed(
|
|
self.addr_scope,
|
|
test_scope2,
|
|
constants.IP_VERSION_4,
|
|
)
|
|
)
|
|
|
|
self.assertFalse(
|
|
self.bgp_driver._address_scope_allowed(
|
|
self.addr_scope,
|
|
test_scope2,
|
|
constants.IP_VERSION_6,
|
|
)
|
|
)
|
|
|
|
def test_expose_subnet(self):
|
|
mock__ensure_network_exposed = mock.patch.object(
|
|
self.bgp_driver, "_ensure_network_exposed"
|
|
).start()
|
|
self.sb_idl.is_router_gateway_on_any_chassis.return_value = (
|
|
self.cr_lrp0
|
|
)
|
|
row = mock.Mock()
|
|
row.datapath = "fake-dp"
|
|
|
|
self.bgp_driver.expose_subnet(None, row)
|
|
|
|
self.sb_idl.is_router_gateway_on_any_chassis.assert_called_once_with(
|
|
row.datapath
|
|
)
|
|
|
|
mock__ensure_network_exposed.assert_called_once_with(
|
|
row, self.cr_lrp0.logical_port
|
|
)
|
|
|
|
def test_expose_subnet_no_gateway_port(self):
|
|
mock__ensure_network_exposed = mock.patch.object(
|
|
self.bgp_driver, "_ensure_network_exposed"
|
|
).start()
|
|
self.sb_idl.is_router_gateway_on_any_chassis.return_value = None
|
|
row = mock.Mock()
|
|
row.datapath = "fake-dp"
|
|
|
|
self.bgp_driver.expose_subnet(None, row)
|
|
|
|
self.sb_idl.is_router_gateway_on_any_chassis.assert_called_once_with(
|
|
row.datapath
|
|
)
|
|
|
|
mock__ensure_network_exposed.assert_not_called()
|
|
|
|
def test_update_subnet(self):
|
|
mock__update_network = mock.patch.object(
|
|
self.bgp_driver, "_update_network"
|
|
).start()
|
|
self.sb_idl.is_router_gateway_on_any_chassis.return_value = (
|
|
self.cr_lrp0
|
|
)
|
|
old = mock.Mock()
|
|
old.mac = ["ff:ff:ff:ff:ff:01 1.1.1.1/24 2.2.2.2/24"]
|
|
|
|
row = mock.Mock()
|
|
row.datapath = "fake-dp"
|
|
row.mac = ["ff:ff:ff:ff:ff:01 2.2.2.2/24 3.3.3.3/24"]
|
|
|
|
self.bgp_driver.update_subnet(old, row)
|
|
|
|
self.sb_idl.is_router_gateway_on_any_chassis.assert_called_once_with(
|
|
row.datapath
|
|
)
|
|
|
|
mock__update_network.assert_called_once_with(
|
|
row, self.cr_lrp0.logical_port, ["3.3.3.3/24"], ["1.1.1.1/24"]
|
|
)
|
|
|
|
@mock.patch.object(linux_net, "get_exposed_routes_on_network")
|
|
@mock.patch.object(linux_net, "del_ip_route")
|
|
@mock.patch.object(linux_net, "add_ip_route")
|
|
def test__update_network(
|
|
self,
|
|
mock_add_ip_route,
|
|
mock_del_ip_route,
|
|
mock_get_exposed_routes_on_network,
|
|
):
|
|
gateway = {}
|
|
gateway["ips"] = [
|
|
ipaddress.ip_interface(ip)
|
|
for ip in ["10.0.0.10/26", "fd51:f4b3:872:eda::10/64"]
|
|
]
|
|
gateway["address_scopes"] = self.addr_scope
|
|
gateway["lrp_ports"] = set()
|
|
self.bgp_driver.ovn_local_cr_lrps = {"gateway_port": gateway}
|
|
|
|
self.router_lrp = mock.Mock()
|
|
self.router_lrp.mac = [
|
|
"ff:ff:ff:ff:ff:01 192.168.1.1/24 fdcc:8cf2:d40c:2::1/64"
|
|
]
|
|
|
|
add_ips = ["192.168.1.1/24", "fdcc:8cf2:d40c:2::1/64"]
|
|
delete_ips = ["192.168.0.1/24"]
|
|
|
|
mock_get_exposed_routes_on_network.side_effect = (
|
|
["route-v4"],
|
|
["route-v6"],
|
|
)
|
|
|
|
self.sb_idl.get_port_by_name.return_value = self.fake_patch_port
|
|
|
|
self.bgp_driver._update_network(
|
|
self.router_port, "gateway_port", add_ips, delete_ips
|
|
)
|
|
|
|
self.sb_idl.get_port_by_name.assert_called_once_with(
|
|
"fake-logical-port"
|
|
)
|
|
|
|
expected_calls = [
|
|
mock.call(
|
|
mock.ANY,
|
|
"10.0.0.0",
|
|
CONF.bgp_vrf_table_id,
|
|
CONF.bgp_nic,
|
|
vlan=None,
|
|
mask=26,
|
|
via=None,
|
|
),
|
|
mock.call(
|
|
mock.ANY,
|
|
"192.168.1.0",
|
|
CONF.bgp_vrf_table_id,
|
|
CONF.bgp_nic,
|
|
vlan=None,
|
|
mask=24,
|
|
via="10.0.0.10",
|
|
),
|
|
mock.call(
|
|
mock.ANY,
|
|
"fd51:f4b3:872:eda::",
|
|
CONF.bgp_vrf_table_id,
|
|
CONF.bgp_nic,
|
|
vlan=None,
|
|
mask=64,
|
|
via=None,
|
|
),
|
|
mock.call(
|
|
mock.ANY,
|
|
"fdcc:8cf2:d40c:2::",
|
|
CONF.bgp_vrf_table_id,
|
|
CONF.bgp_nic,
|
|
vlan=None,
|
|
mask=64,
|
|
via="fd51:f4b3:872:eda::10",
|
|
),
|
|
]
|
|
|
|
mock_add_ip_route.assert_has_calls(expected_calls)
|
|
mock_del_ip_route.assert_called_once_with(
|
|
mock.ANY,
|
|
"192.168.0.0",
|
|
CONF.bgp_vrf_table_id,
|
|
CONF.bgp_nic,
|
|
vlan=None,
|
|
mask=24,
|
|
via="10.0.0.10",
|
|
)
|
|
|
|
self.assertDictEqual(
|
|
self.bgp_driver.propagated_lrp_ports,
|
|
{
|
|
self.router_port.logical_port: {
|
|
"cr_lrp": "gateway_port",
|
|
"subnets": {
|
|
"fdcc:8cf2:d40c:2::/64",
|
|
"192.168.1.0/24"
|
|
}
|
|
}
|
|
}
|
|
)
|
|
|
|
@mock.patch.object(linux_net, "get_exposed_routes_on_network")
|
|
@mock.patch.object(linux_net, "del_ip_route")
|
|
@mock.patch.object(linux_net, "add_ip_route")
|
|
def test__update_network_no_gateway(
|
|
self,
|
|
mock_add_ip_route,
|
|
mock_del_ip_route,
|
|
mock_get_exposed_routes_on_network,
|
|
):
|
|
self.bgp_driver.ovn_local_cr_lrps = {}
|
|
|
|
self.router_lrp = mock.Mock()
|
|
self.router_lrp.mac = [
|
|
"ff:ff:ff:ff:ff:01 192.168.1.1/24 fdcc:8cf2:d40c:2::1/64"
|
|
]
|
|
|
|
add_ips = ["192.168.1.1/24", "fdcc:8cf2:d40c:2::1/64"]
|
|
delete_ips = ["192.168.0.1/24"]
|
|
|
|
self.bgp_driver._update_network(
|
|
self.router_port, "gateway_port", add_ips, delete_ips
|
|
)
|
|
|
|
mock_get_exposed_routes_on_network.assert_not_called()
|
|
mock_del_ip_route.assert_not_called()
|
|
mock_add_ip_route.assert_not_called()
|
|
self.sb_idl.get_port_by_name.assert_not_called()
|
|
|
|
@mock.patch.object(linux_net, "get_exposed_routes_on_network")
|
|
@mock.patch.object(linux_net, "del_ip_route")
|
|
@mock.patch.object(linux_net, "add_ip_route")
|
|
def test__update_network_no_mac(
|
|
self,
|
|
mock_add_ip_route,
|
|
mock_del_ip_route,
|
|
mock_get_exposed_routes_on_network,
|
|
):
|
|
gateway = {}
|
|
gateway["ips"] = [
|
|
ipaddress.ip_interface(ip)
|
|
for ip in ["10.0.0.10/26", "fd51:f4b3:872:eda::10/64"]
|
|
]
|
|
gateway["address_scopes"] = self.addr_scope
|
|
self.bgp_driver.ovn_local_cr_lrps = {"gateway_port": gateway}
|
|
|
|
self.router_port.mac = []
|
|
|
|
add_ips = ["192.168.1.1/24", "fdcc:8cf2:d40c:2::1/64"]
|
|
delete_ips = ["192.168.0.1/24"]
|
|
|
|
self.bgp_driver._update_network(
|
|
self.router_port, "gateway_port", add_ips, delete_ips
|
|
)
|
|
|
|
mock_get_exposed_routes_on_network.assert_not_called()
|
|
mock_del_ip_route.assert_not_called()
|
|
mock_add_ip_route.assert_not_called()
|
|
self.sb_idl.get_port_by_name.assert_not_called()
|
|
|
|
def test_withdraw_subnet(self):
|
|
mock__withdraw_subnet = mock.patch.object(
|
|
self.bgp_driver, "_withdraw_subnet"
|
|
).start()
|
|
|
|
row = mock.Mock()
|
|
row.datapath = "fake-dp"
|
|
row.logical_port = "fake-lport"
|
|
port_info = {
|
|
"cr_lrp": self.cr_lrp0.logical_port,
|
|
"subnets": {
|
|
"fdcc:8cf2:d40c:2::/64",
|
|
"192.168.1.0/24"
|
|
}
|
|
}
|
|
|
|
self.bgp_driver.propagated_lrp_ports = {
|
|
row.logical_port: port_info,
|
|
"another_lrp_port": {}
|
|
}
|
|
self.bgp_driver.ovn_local_cr_lrps = {
|
|
self.cr_lrp0.logical_port: {
|
|
"lrp_ports": set([row.logical_port, "another_lrp_port"])
|
|
}
|
|
}
|
|
|
|
self.bgp_driver.withdraw_subnet(None, row)
|
|
|
|
mock__withdraw_subnet.assert_called_once_with(
|
|
port_info, self.cr_lrp0.logical_port
|
|
)
|
|
self.assertDictEqual(
|
|
self.bgp_driver.propagated_lrp_ports,
|
|
{
|
|
"another_lrp_port": {}
|
|
}
|
|
)
|
|
self.assertDictEqual(
|
|
self.bgp_driver.ovn_local_cr_lrps,
|
|
{
|
|
self.cr_lrp0.logical_port: {
|
|
"lrp_ports": set(["another_lrp_port"])
|
|
}
|
|
}
|
|
)
|
|
|
|
@mock.patch.object(linux_net, "add_ip_route")
|
|
def test__ensure_network_exposed(self, mock_add_ip_route):
|
|
gateway = {}
|
|
gateway["ips"] = [
|
|
ipaddress.ip_interface(ip)
|
|
for ip in ["10.0.0.10/26", "fd51:f4b3:872:eda::10/64"]
|
|
]
|
|
gateway["address_scopes"] = self.addr_scope
|
|
gateway["lrp_ports"] = set()
|
|
self.bgp_driver.ovn_local_cr_lrps = {"gateway_port": gateway}
|
|
|
|
self.router_lrp = mock.Mock()
|
|
self.router_lrp.mac = [
|
|
"ff:ff:ff:ff:ff:01 192.168.1.1/24 fdcc:8cf2:d40c:2::1/64"
|
|
]
|
|
|
|
self.sb_idl.get_port_by_name.return_value = self.fake_patch_port
|
|
|
|
self.bgp_driver._ensure_network_exposed(
|
|
self.router_port, "gateway_port"
|
|
)
|
|
|
|
self.sb_idl.get_port_by_name.assert_called_once_with(
|
|
"fake-logical-port"
|
|
)
|
|
|
|
expected_calls = [
|
|
mock.call(
|
|
mock.ANY,
|
|
"10.0.0.0",
|
|
CONF.bgp_vrf_table_id,
|
|
CONF.bgp_nic,
|
|
vlan=None,
|
|
mask=26,
|
|
via=None,
|
|
),
|
|
mock.call(
|
|
mock.ANY,
|
|
"192.168.1.0",
|
|
CONF.bgp_vrf_table_id,
|
|
CONF.bgp_nic,
|
|
vlan=None,
|
|
mask=24,
|
|
via="10.0.0.10",
|
|
),
|
|
mock.call(
|
|
mock.ANY,
|
|
"fd51:f4b3:872:eda::",
|
|
CONF.bgp_vrf_table_id,
|
|
CONF.bgp_nic,
|
|
vlan=None,
|
|
mask=64,
|
|
via=None,
|
|
),
|
|
mock.call(
|
|
mock.ANY,
|
|
"fdcc:8cf2:d40c:2::",
|
|
CONF.bgp_vrf_table_id,
|
|
CONF.bgp_nic,
|
|
vlan=None,
|
|
mask=64,
|
|
via="fd51:f4b3:872:eda::10",
|
|
),
|
|
]
|
|
|
|
mock_add_ip_route.assert_has_calls(expected_calls)
|
|
self.assertDictEqual(
|
|
self.bgp_driver.ovn_local_cr_lrps,
|
|
{
|
|
'gateway_port': {
|
|
'address_scopes': {
|
|
4: '11111111-1111-1111-1111-11111111',
|
|
6: '22222222-2222-2222-2222-22222222'},
|
|
'ips': [
|
|
ipaddress.IPv4Interface('10.0.0.10/26'),
|
|
ipaddress.IPv6Interface('fd51:f4b3:872:eda::10/64')],
|
|
'lrp_ports': {'lrp-fake-logical-port'}
|
|
}
|
|
}
|
|
)
|
|
self.assertDictEqual(
|
|
self.bgp_driver.propagated_lrp_ports,
|
|
{
|
|
"lrp-fake-logical-port": {
|
|
'cr_lrp': 'gateway_port',
|
|
'subnets': {'192.168.1.0/24', 'fdcc:8cf2:d40c:2::/64'}
|
|
}
|
|
}
|
|
)
|
|
|
|
@mock.patch.object(linux_net, "add_ip_route")
|
|
def test__ensure_network_exposed_invalid_addr_scopes(
|
|
self,
|
|
mock_add_ip_route
|
|
):
|
|
gateway = {}
|
|
gateway["ips"] = [
|
|
ipaddress.ip_interface(ip)
|
|
for ip in ["10.0.0.10/26", "fd51:f4b3:872:eda::10/64"]
|
|
]
|
|
|
|
# Both of them are valid but none of them matches to the correct
|
|
# IP version
|
|
gateway["address_scopes"] = {
|
|
constants.IP_VERSION_4: self.addr_scopev6,
|
|
constants.IP_VERSION_6: self.addr_scopev4,
|
|
}
|
|
gateway["lrp_ports"] = set()
|
|
self.bgp_driver.ovn_local_cr_lrps = {"gateway_port": gateway}
|
|
|
|
self.router_lrp = mock.Mock()
|
|
self.router_lrp.mac = [
|
|
"ff:ff:ff:ff:ff:01 192.168.1.1/24 fdcc:8cf2:d40c:2::1/64"
|
|
]
|
|
|
|
self.sb_idl.get_port_by_name.return_value = self.fake_patch_port
|
|
|
|
self.bgp_driver._ensure_network_exposed(
|
|
self.router_port, "gateway_port"
|
|
)
|
|
|
|
self.sb_idl.get_port_by_name.assert_called_once_with(
|
|
"fake-logical-port"
|
|
)
|
|
mock_add_ip_route.assert_not_called()
|
|
self.assertDictEqual(
|
|
self.bgp_driver.ovn_local_cr_lrps,
|
|
{
|
|
'gateway_port': {
|
|
'address_scopes': {
|
|
4: '22222222-2222-2222-2222-22222222',
|
|
6: '11111111-1111-1111-1111-11111111'},
|
|
'ips': [
|
|
ipaddress.IPv4Interface('10.0.0.10/26'),
|
|
ipaddress.IPv6Interface('fd51:f4b3:872:eda::10/64')],
|
|
'lrp_ports': set()
|
|
}
|
|
}
|
|
)
|
|
self.assertDictEqual(
|
|
self.bgp_driver.propagated_lrp_ports,
|
|
{}
|
|
)
|
|
|
|
@mock.patch.object(linux_net, "add_ip_route")
|
|
def test__ensure_network_exposed_no_gateway(self, mock_add_ip_route):
|
|
self.bgp_driver.ovn_local_cr_lrps = {}
|
|
|
|
self.bgp_driver._ensure_network_exposed(
|
|
self.router_port, "gateway_port"
|
|
)
|
|
|
|
self.sb_idl.get_port_by_name.assert_not_called()
|
|
mock_add_ip_route.assert_not_called()
|
|
self.assertDictEqual(
|
|
self.bgp_driver.propagated_lrp_ports,
|
|
{}
|
|
)
|
|
|
|
@mock.patch.object(linux_net, "add_ip_route")
|
|
def test__ensure_network_exposed_duplicate_ip(self, mock_add_ip_route):
|
|
gateway = {}
|
|
gateway["ips"] = [
|
|
ipaddress.ip_interface(ip)
|
|
for ip in ["192.168.1.1/24", "fd51:f4b3:872:eda::10/64"]
|
|
]
|
|
gateway["address_scopes"] = self.addr_scope
|
|
self.bgp_driver.ovn_local_cr_lrps = {"gateway_port": gateway}
|
|
|
|
self.bgp_driver._ensure_network_exposed(
|
|
self.router_port, "gateway_port"
|
|
)
|
|
|
|
self.sb_idl.get_port_by_name.assert_not_called()
|
|
mock_add_ip_route.assert_not_called()
|
|
self.assertDictEqual(
|
|
self.bgp_driver.propagated_lrp_ports,
|
|
{}
|
|
)
|
|
|
|
@mock.patch.object(linux_net, "add_ip_route")
|
|
def test__ensure_network_exposed_port_not_existing(
|
|
self,
|
|
mock_add_ip_route
|
|
):
|
|
mock__get_addr_scopes = mock.patch.object(
|
|
self.bgp_driver, "_get_addr_scopes"
|
|
).start()
|
|
gateway = {}
|
|
gateway["ips"] = [
|
|
ipaddress.ip_interface(ip)
|
|
for ip in ["10.0.0.10/26", "fd51:f4b3:872:eda::10/64"]
|
|
]
|
|
gateway["address_scopes"] = self.addr_scope
|
|
self.bgp_driver.ovn_local_cr_lrps = {"gateway_port": gateway}
|
|
|
|
self.sb_idl.get_port_by_name.return_value = []
|
|
self.bgp_driver._ensure_network_exposed(
|
|
self.router_port, "gateway_port"
|
|
)
|
|
mock__get_addr_scopes.assert_not_called()
|
|
mock_add_ip_route.assert_not_called()
|
|
self.assertDictEqual(
|
|
self.bgp_driver.propagated_lrp_ports,
|
|
{}
|
|
)
|
|
|
|
@mock.patch.object(linux_net, "add_ip_route")
|
|
def test__ensure_network_exposed_port_addr_scope_no_match(
|
|
self,
|
|
mock_add_ip_route
|
|
):
|
|
gateway = {}
|
|
gateway["ips"] = [
|
|
ipaddress.ip_interface(ip)
|
|
for ip in ["10.0.0.10/26", "fd51:f4b3:872:eda::10/64"]
|
|
]
|
|
gateway["address_scopes"] = {
|
|
constants.IP_VERSION_4: "address_scope_v4",
|
|
constants.IP_VERSION_6: "address_scope_v6",
|
|
}
|
|
self.bgp_driver.ovn_local_cr_lrps = {"gateway_port": gateway}
|
|
|
|
self.sb_idl.get_port_by_name.return_value = self.fake_patch_port
|
|
self.bgp_driver._ensure_network_exposed(
|
|
self.router_port, "gateway_port"
|
|
)
|
|
|
|
self.sb_idl.get_port_by_name.assert_called_once_with(
|
|
"fake-logical-port"
|
|
)
|
|
mock_add_ip_route.assert_not_called()
|
|
self.assertDictEqual(
|
|
self.bgp_driver.propagated_lrp_ports,
|
|
{}
|
|
)
|
|
|
|
@mock.patch.object(linux_net, "get_exposed_routes_on_network")
|
|
@mock.patch.object(linux_net, "del_ip_route")
|
|
def test__withdraw_subnet(
|
|
self, mock_del_ip_route, mock_get_exposed_routes_on_network
|
|
):
|
|
gateway = {}
|
|
gateway["ips"] = [
|
|
ipaddress.ip_interface(ip)
|
|
for ip in ["10.0.0.10/26", "fd51:f4b3:872:eda::10/64"]
|
|
]
|
|
gateway["address_scopes"] = self.addr_scope
|
|
gateway["lrp_ports"] = set([""])
|
|
self.bgp_driver.ovn_local_cr_lrps = {"gateway_port": gateway}
|
|
port_info = {
|
|
"cr_lrp": self.cr_lrp0.logical_port,
|
|
"subnets": {
|
|
"fdcc:8cf2:d40c:2::/64",
|
|
"192.168.1.0/24"
|
|
}
|
|
}
|
|
|
|
mock_get_exposed_routes_on_network.side_effect = (["route-v4"], [])
|
|
|
|
self.bgp_driver._withdraw_subnet(port_info, "gateway_port")
|
|
|
|
expected_calls = [
|
|
mock.call(
|
|
mock.ANY,
|
|
"192.168.1.0",
|
|
CONF.bgp_vrf_table_id,
|
|
CONF.bgp_nic,
|
|
vlan=None,
|
|
mask=24,
|
|
via="10.0.0.10",
|
|
),
|
|
mock.call(
|
|
mock.ANY,
|
|
"fdcc:8cf2:d40c:2::",
|
|
CONF.bgp_vrf_table_id,
|
|
CONF.bgp_nic,
|
|
vlan=None,
|
|
mask=64,
|
|
via="fd51:f4b3:872:eda::10",
|
|
),
|
|
mock.call(
|
|
mock.ANY,
|
|
"fd51:f4b3:872:eda::",
|
|
CONF.bgp_vrf_table_id,
|
|
CONF.bgp_nic,
|
|
vlan=None,
|
|
mask=64,
|
|
via=None,
|
|
),
|
|
]
|
|
|
|
mock_del_ip_route.assert_has_calls(expected_calls)
|
|
|
|
@mock.patch.object(linux_net, "get_exposed_routes_on_network")
|
|
@mock.patch.object(linux_net, "del_ip_route")
|
|
def test__withdraw_subnet_no_gateway(
|
|
self, mock_del_ip_route, mock_get_exposed_routes_on_network
|
|
):
|
|
self.bgp_driver.ovn_local_cr_lrps = {}
|
|
self.bgp_driver._withdraw_subnet(self.router_port, "gateway_port")
|
|
mock_del_ip_route.assert_not_called()
|
|
mock_get_exposed_routes_on_network.assert_not_called()
|
|
|
|
@mock.patch.object(linux_net, "delete_ip_routes")
|
|
@mock.patch.object(linux_net, "get_routes_on_tables")
|
|
def test_sync(self, mock_get_routes_on_tables, mock_delete_ip_routes):
|
|
def create_route(dst, dst_len, gateway):
|
|
m = mock.Mock([])
|
|
m.dst = dst
|
|
m.dst_len = dst_len
|
|
m.gateway = gateway
|
|
return m
|
|
|
|
def create_hashed_route(dst, dst_len, gateway):
|
|
return ovn_stretched_l2_bgp_driver.HashedRoute(
|
|
network=dst,
|
|
prefix_len=dst_len,
|
|
dst=gateway,
|
|
)
|
|
|
|
mock__expose_cr_lrp = mock.patch.object(
|
|
self.bgp_driver, "_expose_cr_lrp"
|
|
).start()
|
|
|
|
vrf_routes = [
|
|
create_hashed_route(dst, dst_len, gateway)
|
|
for (dst, dst_len, gateway) in [
|
|
("192.168.1.0", 24, "10.0.0.1"),
|
|
("10.0.0.0", 24, None),
|
|
("fdcc:8cf2:d40c:2::", 64, "fd51:f4b3:872:eda::1"),
|
|
("fd51:f4b3:872:eda::", 64, None),
|
|
]
|
|
]
|
|
|
|
# really hacky way to get the routes into self.bgp_driver.vrf_routes
|
|
mock__expose_cr_lrp.side_effect = (
|
|
lambda _, __: self.bgp_driver.vrf_routes.update(vrf_routes)
|
|
)
|
|
|
|
self.sb_idl.get_cr_lrp_ports.return_value = [self.cr_lrp0]
|
|
|
|
delete_route = create_route("192.168.0.0", 24, "10.0.0.1")
|
|
routes = [
|
|
create_route(dst, dst_len, gateway)
|
|
for (dst, dst_len, gateway) in [
|
|
("192.168.1.0", 24, "10.0.0.1"),
|
|
("10.0.0.0", 24, None),
|
|
("fdcc:8cf2:d40c:2::", 64, "fd51:f4b3:872:eda::1"),
|
|
("fd51:f4b3:872:eda::", 64, None),
|
|
]
|
|
]
|
|
routes.append(delete_route)
|
|
|
|
mock_get_routes_on_tables.return_value = routes
|
|
|
|
self.bgp_driver.sync()
|
|
|
|
mock_get_routes_on_tables.assert_called_once_with(
|
|
[CONF.bgp_vrf_table_id]
|
|
)
|
|
mock_delete_ip_routes.assert_called_once_with([delete_route])
|
|
mock__expose_cr_lrp.assert_called_once_with(
|
|
["10.0.0.1/24", "fd51:f4b3:872:eda::1/64"], self.cr_lrp0
|
|
)
|
|
|
|
def test_withdraw_ip(self):
|
|
mock__withdraw_cr_lrp = mock.patch.object(
|
|
self.bgp_driver, "_withdraw_cr_lrp"
|
|
).start()
|
|
|
|
self.bgp_driver.withdraw_ip(None, self.cr_lrp0)
|
|
|
|
mock__withdraw_cr_lrp.assert_called_once_with(None, self.cr_lrp0)
|
|
|
|
def test__withdraw_cr_lrp(self):
|
|
mock__withdraw_subnet = mock.patch.object(
|
|
self.bgp_driver, "_withdraw_subnet"
|
|
).start()
|
|
|
|
gateway = {}
|
|
gateway["ips"] = [
|
|
ipaddress.ip_interface(ip)
|
|
for ip in ["10.0.0.10/26", "fd51:f4b3:872:eda::10/64"]
|
|
]
|
|
gateway["address_scopes"] = self.addr_scope
|
|
self.bgp_driver.ovn_local_cr_lrps = {
|
|
self.cr_lrp0.logical_port: gateway
|
|
}
|
|
gateway["lrp_ports"] = set([
|
|
"lrp-lrp_port0",
|
|
"lrp-lrp_port1",
|
|
"lrp-lrp_port2",
|
|
])
|
|
|
|
lrp_port0 = {
|
|
"cr_lrp": self.cr_lrp0.logical_port,
|
|
"subnets": set([
|
|
"fdcc:8cf2:d40c:1::/64",
|
|
"192.168.0.0/24"])
|
|
}
|
|
lrp_port1 = {
|
|
"cr_lrp": self.cr_lrp0.logical_port,
|
|
"subnets": set([
|
|
"fdcc:8cf2:d40c:2::/64",
|
|
"192.168.1.0/24"])
|
|
}
|
|
|
|
self.bgp_driver.propagated_lrp_ports = {
|
|
"lrp-lrp_port0": lrp_port0,
|
|
"lrp-lrp_port1": lrp_port1,
|
|
}
|
|
self.bgp_driver.ovn_local_cr_lrps = {
|
|
self.cr_lrp0.logical_port: gateway
|
|
}
|
|
|
|
self.bgp_driver._withdraw_cr_lrp(None, self.cr_lrp0)
|
|
mock__withdraw_subnet.assert_has_calls(
|
|
[
|
|
mock.call(lrp_port0, self.cr_lrp0.logical_port),
|
|
mock.call(lrp_port1, self.cr_lrp0.logical_port),
|
|
],
|
|
any_order=True
|
|
)
|
|
self.assertDictEqual(
|
|
self.bgp_driver.ovn_local_cr_lrps,
|
|
{}
|
|
)
|
|
self.assertDictEqual(
|
|
self.bgp_driver.propagated_lrp_ports,
|
|
{}
|
|
)
|
|
|
|
def test__withdraw_cr_lrp_invalid_addr_scope(self):
|
|
mock__withdraw_subnet = mock.patch.object(
|
|
self.bgp_driver, "_withdraw_subnet"
|
|
).start()
|
|
|
|
gateway = {
|
|
"address_scopes": {
|
|
constants.IP_VERSION_4: '',
|
|
constants.IP_VERSION_6: '',
|
|
}
|
|
}
|
|
gateway["lrp_ports"] = set([
|
|
"lrp-lrp_port0",
|
|
"lrp-lrp_port1",
|
|
"lrp-lrp_port2",
|
|
])
|
|
self.bgp_driver.propagated_lrp_ports = {
|
|
"lrp-lrp_port0": {},
|
|
"lrp-lrp_port1": {},
|
|
"lrp-lrp_port2": {},
|
|
}
|
|
self.bgp_driver.ovn_local_cr_lrps = {
|
|
self.cr_lrp0.logical_port: gateway
|
|
}
|
|
|
|
self.bgp_driver._withdraw_cr_lrp(None, self.cr_lrp0)
|
|
|
|
self.sb_idl.get_lrp_ports_for_router.assert_not_called()
|
|
mock__withdraw_subnet.assert_not_called()
|
|
|
|
def test_expose_ip(self):
|
|
mock__expose_cr_lrp = mock.patch.object(
|
|
self.bgp_driver, "_expose_cr_lrp"
|
|
).start()
|
|
|
|
ips = ["10.0.0.1/24", "fd51:f4b3:872:eda::1/64"]
|
|
|
|
self.bgp_driver.expose_ip(ips, self.cr_lrp0)
|
|
|
|
mock__expose_cr_lrp.assert_called_once_with(ips, self.cr_lrp0)
|
|
|
|
def test_expose_ip_invalid_type(self):
|
|
mock__expose_cr_lrp = mock.patch.object(
|
|
self.bgp_driver, "_expose_cr_lrp"
|
|
).start()
|
|
|
|
patch_port = mock.Mock()
|
|
patch_port.type = constants.OVN_PATCH_VIF_PORT_TYPE
|
|
|
|
self.bgp_driver.expose_ip([], patch_port)
|
|
|
|
mock__expose_cr_lrp.assert_not_called()
|
|
|
|
def test__expose_cr_lrp(self):
|
|
mock__ensure_network_exposed = mock.patch.object(
|
|
self.bgp_driver, "_ensure_network_exposed"
|
|
).start()
|
|
|
|
lrp_port0 = fakes.create_object(
|
|
{
|
|
"name": "fake-port-lrp0",
|
|
"type": constants.OVN_PATCH_VIF_PORT_TYPE,
|
|
"chassis": "fake-chassis1",
|
|
"external_ids": {},
|
|
"logical_port": "lrp-lrp_port0",
|
|
"options": {
|
|
"chassis-redirect-port": self.cr_lrp0.logical_port,
|
|
},
|
|
}
|
|
)
|
|
|
|
lrp_port1 = fakes.create_object(
|
|
{
|
|
"name": "fake-port-lrp1",
|
|
"type": constants.OVN_PATCH_VIF_PORT_TYPE,
|
|
"mac": ["aa:bb:cc:dd:ee:ee 192.168.1.12 192.168.1.13"],
|
|
"logical_port": "lrp-lrp_port1",
|
|
"chassis": "fake-chassis1",
|
|
"external_ids": {},
|
|
"options": {},
|
|
}
|
|
)
|
|
|
|
lrp_port2 = fakes.create_object(
|
|
{
|
|
"name": "fake-port-lrp2",
|
|
"type": constants.OVN_PATCH_VIF_PORT_TYPE,
|
|
"mac": [],
|
|
"logical_port": "lrp-lrp_port2",
|
|
"chassis": "fake-chassis1",
|
|
"external_ids": {},
|
|
"options": {},
|
|
}
|
|
)
|
|
|
|
lrp_port3 = fakes.create_object(
|
|
{
|
|
"name": "fake-port-lrp3",
|
|
"type": constants.OVN_PATCH_VIF_PORT_TYPE,
|
|
"mac": [],
|
|
"logical_port": "lrp-lrp_port3",
|
|
"chassis": "",
|
|
"up": [False],
|
|
"external_ids": {},
|
|
"options": {},
|
|
}
|
|
)
|
|
|
|
lrp_port4 = fakes.create_object(
|
|
{
|
|
"name": "fake-port-lrp4",
|
|
"type": constants.OVN_PATCH_VIF_PORT_TYPE,
|
|
"mac": [],
|
|
"logical_port": "lrp-lrp_port4",
|
|
"chassis": "",
|
|
"up": [False],
|
|
"options": {},
|
|
}
|
|
)
|
|
|
|
lrp_port5 = fakes.create_object(
|
|
{
|
|
"name": "fake-port-lrp5",
|
|
"type": constants.OVN_PATCH_VIF_PORT_TYPE,
|
|
"mac": [],
|
|
"logical_port": "lrp-lrp_port5",
|
|
"chassis": "",
|
|
"up": [False],
|
|
"options": {
|
|
"chassis-redirect-port": self.cr_lrp0.logical_port,
|
|
},
|
|
}
|
|
)
|
|
|
|
self.sb_idl.get_lrp_ports_for_router.return_value = [
|
|
lrp_port0,
|
|
lrp_port1,
|
|
lrp_port2,
|
|
lrp_port3,
|
|
lrp_port4,
|
|
lrp_port5,
|
|
]
|
|
|
|
self.sb_idl.get_port_by_name.return_value = self.fake_patch_port
|
|
|
|
ips = ["10.0.0.1/24", "fd51:f4b3:872:eda::1/64"]
|
|
|
|
self.bgp_driver._expose_cr_lrp(ips, self.cr_lrp0)
|
|
|
|
mock__ensure_network_exposed.assert_has_calls(
|
|
[
|
|
mock.call(lrp_port3, self.cr_lrp0.logical_port),
|
|
mock.call(lrp_port4, self.cr_lrp0.logical_port),
|
|
]
|
|
)
|
|
|
|
self.sb_idl.get_port_by_name.assert_called_once_with("fake-port")
|
|
|
|
self.assertEqual(
|
|
{
|
|
self.cr_lrp0.logical_port: {
|
|
"ips": [ipaddress.ip_interface(ip) for ip in ips],
|
|
"address_scopes": self.addr_scope,
|
|
"lrp_ports": set()
|
|
}
|
|
},
|
|
self.bgp_driver.ovn_local_cr_lrps)
|
|
|
|
def test__expose_cr_lrp_no_port(self):
|
|
mock__ensure_network_exposed = mock.patch.object(
|
|
self.bgp_driver, "_ensure_network_exposed"
|
|
).start()
|
|
|
|
self.sb_idl.get_port_by_name.return_value = []
|
|
|
|
ips = ["10.0.0.1/24", "fd51:f4b3:872:eda::1/64"]
|
|
|
|
self.bgp_driver._expose_cr_lrp(ips, self.cr_lrp0)
|
|
|
|
mock__ensure_network_exposed.assert_not_called()
|
|
self.sb_idl.get_port_by_name.assert_called_once_with("fake-port")
|
|
|
|
def test__expose_cr_lrp_no_addr_scope(self):
|
|
mock__ensure_network_exposed = mock.patch.object(
|
|
self.bgp_driver, "_ensure_network_exposed"
|
|
).start()
|
|
mock__get_addr_scopes = mock.patch.object(
|
|
self.bgp_driver, "_get_addr_scopes"
|
|
).start()
|
|
|
|
self.sb_idl.get_port_by_name.return_value = self.fake_patch_port
|
|
|
|
mock__get_addr_scopes.return_value = {
|
|
constants.IP_VERSION_4: "address_scope_v4",
|
|
constants.IP_VERSION_6: "address_scope_v6",
|
|
}
|
|
|
|
self.bgp_driver._expose_cr_lrp([], self.cr_lrp0)
|
|
|
|
self.sb_idl.get_port_by_name.assert_called_once_with("fake-port")
|
|
mock__get_addr_scopes.assert_called_once_with(self.fake_patch_port)
|
|
self.sb_idl.get_lrp_ports_for_router.assert_not_called()
|
|
mock__ensure_network_exposed.assert_not_called()
|
|
|
|
def test_expose_remote_ip(self):
|
|
self.assertRaises(
|
|
NotImplementedError,
|
|
self.bgp_driver.expose_remote_ip,
|
|
"1.2.3.4/24")
|
|
|
|
def test_withdraw_remote_ip(self):
|
|
self.assertRaises(
|
|
NotImplementedError,
|
|
self.bgp_driver.withdraw_remote_ip,
|
|
"1.2.3.4/24")
|