def test_list_interface_ips(self): type = futils.IPV4 tap = "tap" + str(uuid.uuid4())[:11] retcode = futils.CommandOutput("", "") with mock.patch('calico.felix.futils.check_call', return_value=retcode): ips = devices.list_interface_ips(type, tap) futils.check_call.assert_called_once_with( ["ip", "route", "list", "dev", tap]) self.assertFalse(ips) stdout = "10.11.9.90 scope link" retcode = futils.CommandOutput(stdout, "") with mock.patch('calico.felix.futils.check_call', return_value=retcode): ips = devices.list_interface_ips(type, tap) futils.check_call.assert_called_once_with( ["ip", "route", "list", "dev", tap]) self.assertEqual(ips, set(["10.11.9.90"])) stdout = "10.11.9.90 scope link\nblah-di-blah not valid\nx\n" retcode = futils.CommandOutput(stdout, "") with mock.patch('calico.felix.futils.check_call', return_value=retcode): ips = devices.list_interface_ips(type, tap) futils.check_call.assert_called_once_with( ["ip", "route", "list", "dev", tap]) self.assertEqual(ips, set(["10.11.9.90"])) type = futils.IPV6 stdout = "2001:: scope link\n" retcode = futils.CommandOutput(stdout, "") with mock.patch('calico.felix.futils.check_call', return_value=retcode): ips = devices.list_interface_ips(type, tap) futils.check_call.assert_called_once_with( ["ip", "-6", "route", "list", "dev", tap]) self.assertEqual(ips, set(["2001::"])) stdout = "2001:: scope link\n\n" retcode = futils.CommandOutput(stdout, "") with mock.patch('calico.felix.futils.check_call', return_value=retcode): ips = devices.list_interface_ips(type, tap) futils.check_call.assert_called_once_with( ["ip", "-6", "route", "list", "dev", tap]) self.assertEqual(ips, set(["2001::"]))
def test_list_ips_by_iface_v4_mainline(self): retval = futils.CommandOutput( "1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default \n" " inet 127.0.0.1/8 scope host lo\n" " valid_lft forever preferred_lft forever\n" "2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000\n" " inet 192.168.171.128/24 brd 192.168.171.255 scope global eth0\n" " valid_lft forever preferred_lft forever\n" "3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000\n" " inet 172.16.171.5/24 brd 172.16.171.255 scope global eth1\n" " valid_lft forever preferred_lft forever\n" "5: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default \n" " inet 172.17.0.1/16 scope global docker0\n" " valid_lft forever preferred_lft forever\n" "6: lxcbr0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN group default \n" " inet 10.0.3.1/24 brd 10.0.3.255 scope global lxcbr0\n" " valid_lft forever preferred_lft forever\n" " inet 10.0.3.2/24 brd 10.0.3.255 scope global lxcbr0\n" " valid_lft forever preferred_lft forever\n", "" ) with mock.patch('calico.felix.futils.check_call', return_value=retval) as m_check_call: ips = devices.list_ips_by_iface(futils.IPV4) self.assertEqual( ips, { "lo": {IPAddress("127.0.0.1")}, "eth0": {IPAddress("192.168.171.128")}, "eth1": {IPAddress("172.16.171.5")}, "docker0": {IPAddress("172.17.0.1")}, "lxcbr0": {IPAddress("10.0.3.1"), IPAddress("10.0.3.2")}, } )
def test_configure_interface_ipv6_mainline(self): """ Test that configure_interface_ipv6_mainline - opens and writes to the /proc system to enable proxy NDP on the interface. - calls ip -6 neigh to set up the proxy targets. Mainline test has two proxy targets. """ m_open = mock.mock_open() rc = futils.CommandOutput("", "") if_name = "tap3e5a2b34222" proxy_target = "2001::3:4" open_patch = mock.patch('__builtin__.open', m_open, create=True) m_check_call = mock.patch('calico.felix.futils.check_call', return_value=rc) with nested(open_patch, m_check_call) as (_, m_check_call): devices.configure_interface_ipv6(if_name, proxy_target) calls = [mock.call('/proc/sys/net/ipv6/conf/%s/proxy_ndp' % if_name, 'wb'), M_ENTER, mock.call().write('1'), M_CLEAN_EXIT] m_open.assert_has_calls(calls) ip_calls = [mock.call(["ip", "-6", "neigh", "add", "proxy", str(proxy_target), "dev", if_name])] m_check_call.assert_has_calls(ip_calls)
def test_flush(self): retcode = futils.CommandOutput("", "") with mock.patch('calico.felix.futils.check_call', return_value=retcode): ipsets.flush("a") futils.check_call.assert_called_with(["ipset", "flush", "a"])
def test_add_route(self): tap = "tap" + str(uuid.uuid4())[:11] mac = stub_utils.get_mac() retcode = futils.CommandOutput("", "") type = futils.IPV4 ip = "1.2.3.4" with mock.patch('calico.felix.futils.check_call', return_value=retcode): devices.add_route(type, ip, tap, mac) futils.check_call.assert_any_call( ['arp', '-s', ip, mac, '-i', tap]) futils.check_call.assert_called_with( ["ip", "route", "replace", ip, "dev", tap]) with mock.patch("calico.felix.futils.check_call") as m_check_call: devices.add_route(type, ip, tap, None) type = futils.IPV6 ip = "2001::" with mock.patch('calico.felix.futils.check_call', return_value=retcode): devices.add_route(type, ip, tap, mac) futils.check_call.assert_called_with( ["ip", "-6", "route", "replace", ip, "dev", tap]) with mock.patch("calico.felix.futils.check_call") as m_check_call: devices.add_route(type, ip, tap, None)
def test_list_names(self): retcode = futils.CommandOutput( "Name: one\nName:a\nblah\nfee fi fo fum\nNomatch\n" + "Name: two\nfdsjk\n\nfdjk\nName:\nb\nName: three\n", "") with mock.patch('calico.felix.futils.check_call', return_value=retcode): names = ipsets.list_names() futils.check_call.assert_called_with(["ipset", "list"]) self.assertEqual(names, ["one", "two", "three"]) retcode = futils.CommandOutput("", "") with mock.patch('calico.felix.futils.check_call', return_value=retcode): names = ipsets.list_names() futils.check_call.assert_called_with(["ipset", "list"]) self.assertEqual(names, [])
def test_list_ips_by_iface_v6_mainline(self): retval = futils.CommandOutput( "1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 \n" " inet6 ::1/128 scope host \n" " valid_lft forever preferred_lft forever\n" "2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qlen 1000\n" " inet6 fe80::20c:29ff:fecb:c819/64 scope link \n" " valid_lft forever preferred_lft forever\n" "4: mgmt0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 \n" " inet6 fe80::1/64 scope link \n" " valid_lft forever preferred_lft forever\n" " inet6 fe80::8872:90ff:fec4:f79e/64 scope link \n" " valid_lft forever preferred_lft forever\n", "" ) with mock.patch('calico.felix.futils.check_call', return_value=retval) as m_check_call: ips = devices.list_ips_by_iface(futils.IPV6) self.assertEqual( ips, { "lo": {IPAddress("::1")}, "eth0": {IPAddress("fe80::20c:29ff:fecb:c819")}, "mgmt0": {IPAddress("fe80::1"), IPAddress("fe80::8872:90ff:fec4:f79e")}, } )
def test_add(self): retcode = futils.CommandOutput("", "") with mock.patch('calico.felix.futils.check_call', return_value=retcode): ipsets.add("a", "b") futils.check_call.assert_called_with( ["ipset", "add", "a", "b", "-exist"])
def test_set_routes_nothing_to_do(self): type = futils.IPV4 ips = set(["1.2.3.4", "2.3.4.5"]) retcode = futils.CommandOutput("", "") interface = "tapabcdef" mac = stub_utils.get_mac() with mock.patch('calico.felix.futils.check_call', return_value=retcode): with mock.patch('calico.felix.devices.list_interface_route_ips', return_value=ips): devices.set_routes(type, ips, interface, mac) self.assertEqual(futils.check_call.call_count, 0)
def test_list_interface_no_ips(self): retcode = futils.CommandOutput( "7: tunl0@NONE: <NOARP,UP,LOWER_UP> mtu 1440 qdisc noqueue " "state UNKNOWN group default\n" " link/ipip 0.0.0.0 brd 0.0.0.0\n", "") with mock.patch('calico.felix.futils.check_call', return_value=retcode) as m_check_call: ips = devices.list_interface_ips(futils.IPV4, "tunl0") self.assertEqual( m_check_call.mock_calls, [mock.call(["ip", "addr", "list", "dev", "tunl0"])]) self.assertEqual(ips, set())
def test_destroy(self): retcode = futils.CommandOutput("", "") with mock.patch('calico.felix.futils.call_silent', return_value=0): with mock.patch('calico.felix.futils.check_call', return_value=retcode): ipsets.destroy("a") futils.call_silent.assert_called_with(["ipset", "list", "a"]) futils.check_call.assert_called_with(["ipset", "destroy", "a"]) with mock.patch('calico.felix.futils.call_silent', return_value=1): with mock.patch('calico.felix.futils.check_call', return_value=retcode): ipsets.destroy("a") futils.call_silent.assert_called_with(["ipset", "list", "a"]) self.assertFalse(futils.check_call.called)
def test_del_route(self): tap = "tap" + str(uuid.uuid4())[:11] retcode = futils.CommandOutput("", "") type = futils.IPV4 ip = "1.2.3.4" with mock.patch('calico.felix.futils.check_call', return_value=retcode): devices.del_route(type, ip, tap) futils.check_call.assert_any_call(['arp', '-d', ip, '-i', tap]) futils.check_call.assert_called_with(["ip", "route", "del", ip, "dev", tap]) type = futils.IPV6 ip = "2001::" with mock.patch('calico.felix.futils.check_call', return_value=retcode): devices.del_route(type, ip, tap) futils.check_call.assert_called_once_with(["ip", "-6", "route", "del", ip, "dev", tap])
def test_set_routes_mainline(self): type = futils.IPV4 ips = set(["1.2.3.4", "2.3.4.5"]) interface = "tapabcdef" mac = stub_utils.get_mac() calls = [mock.call(['arp', '-s', "1.2.3.4", mac, '-i', interface]), mock.call(["ip", "route", "replace", "1.2.3.4", "dev", interface]), mock.call(['arp', '-s', "2.3.4.5", mac, '-i', interface]), mock.call(["ip", "route", "replace", "2.3.4.5", "dev", interface])] with mock.patch('calico.felix.futils.check_call', return_value=futils.CommandOutput("", "")): with mock.patch('calico.felix.devices.list_interface_route_ips', return_value=set()): devices.set_routes(type, ips, interface, mac) self.assertEqual(futils.check_call.call_count, len(calls)) futils.check_call.assert_has_calls(calls, any_order=True)
def test_set_routes_changed_ips_reset_arp(self, m_remove_conntrack): type = futils.IPV4 ips = set(["1.2.3.4", "2.3.4.5"]) interface = "tapabcdef" mac = stub_utils.get_mac() retcode = futils.CommandOutput("", "") current_ips = set(["2.3.4.5", "3.4.5.6"]) calls = [mock.call(['arp', '-s', "1.2.3.4", mac, '-i', interface]), mock.call(["ip", "route", "replace", "1.2.3.4", "dev", interface]), mock.call(['arp', '-s', "2.3.4.5", mac, '-i', interface]), mock.call(['arp', '-d', "3.4.5.6", '-i', interface]), mock.call(["ip", "route", "del", "3.4.5.6", "dev", interface])] with mock.patch('calico.felix.futils.check_call', return_value=retcode): with mock.patch('calico.felix.devices.list_interface_route_ips', return_value=current_ips): devices.set_routes(type, ips, interface, mac, reset_arp=True) self.assertEqual(futils.check_call.call_count, len(calls)) futils.check_call.assert_has_calls(calls, any_order=True) m_remove_conntrack.assert_called_once_with(set(["3.4.5.6"]), 4)
def test_list_interface_v6_with_ips(self): retcode = futils.CommandOutput( "7: tunl0@NONE: <NOARP,UP,LOWER_UP> mtu 1440 qdisc noqueue " "state UNKNOWN group default\n" " link/ipip 0.0.0.0 brd 0.0.0.0\n" " inet6 5678::/64 brd foobar scope global tunl0\n" " inet6 ABcd::/64 brd foobar scope global tunl0\n" # Allow for dotted quad translated v4 addresses, just in case. " inet6 ::ffff:192.0.2.128/128 brd foobar scope global tunl0\n", "" ) with mock.patch('calico.felix.futils.check_call', return_value=retcode) as m_check_call: ips = devices.list_interface_ips(futils.IPV6, "tunl0") self.assertEqual( m_check_call.mock_calls, [mock.call(["ip", "-6", "addr", "list", "dev", "tunl0"])] ) self.assertEqual(ips, set([IPAddress("5678::"), IPAddress("abcd::"), IPAddress("::ffff:c000:0280")]))
def test_on_interface_update_v6(self): combined_id = EndpointId("host_id", "orchestrator_id", "workload_id", "endpoint_id") ip_type = futils.IPV6 retcode = futils.CommandOutput("", "") local_ep = self.get_local_endpoint(combined_id, ip_type) ips = ["1234::5678"] iface = "tapabcdef" data = { 'endpoint': "endpoint_id", 'mac': stub_utils.get_mac(), 'name': iface, 'ipv6_nets': ips, 'profile_ids': []} # We can only get on_interface_update calls after the first # on_endpoint_update, so trigger that. with mock.patch('calico.felix.devices.set_routes'): with mock.patch('calico.felix.devices.configure_interface_ipv6'): local_ep.on_endpoint_update(data, async=False) self.assertEqual(local_ep._mac, data['mac']) devices.configure_interface_ipv6.assert_called_once_with(iface, None) devices.set_routes.assert_called_once_with(ip_type, set(ips), iface, data['mac'], reset_arp=False) # Now pretend to get an interface update - does all the same work. with mock.patch('calico.felix.devices.set_routes'): with mock.patch('calico.felix.devices.configure_interface_ipv6'): local_ep.on_interface_update() devices.configure_interface_ipv6.assert_called_once_with(iface, None) devices.set_routes.assert_called_once_with(ip_type, set(ips), iface, data['mac'], reset_arp=False)
def test_on_endpoint_update_v4(self): combined_id = EndpointId("host_id", "orchestrator_id", "workload_id", "endpoint_id") ip_type = futils.IPV4 retcode = futils.CommandOutput("", "") local_ep = self.get_local_endpoint(combined_id, ip_type) # Call with no data; should be ignored (no configuration to remove). local_ep.on_endpoint_update(None, async=False) ips = ["1.2.3.4"] iface = "tapabcdef" data = { 'endpoint': "endpoint_id", 'mac': stub_utils.get_mac(), 'name': iface, 'ipv4_nets': ips, 'profile_ids': []} # Report an initial update (endpoint creation) and check configured with mock.patch('calico.felix.devices.set_routes'): with mock.patch('calico.felix.devices.configure_interface_ipv4'): local_ep.on_endpoint_update(data, async=False) self.assertEqual(local_ep._mac, data['mac']) devices.configure_interface_ipv4.assert_called_once_with(iface) devices.set_routes.assert_called_once_with(ip_type, set(ips), iface, data['mac'], reset_arp=True) # Send through an update with no changes - should redo without # resetting ARP. with mock.patch('calico.felix.devices.set_routes'): with mock.patch('calico.felix.devices.configure_interface_ipv4'): local_ep.on_endpoint_update(data, async=False) self.assertEqual(local_ep._mac, data['mac']) devices.configure_interface_ipv4.assert_called_once_with(iface) devices.set_routes.assert_called_once_with(ip_type, set(ips), iface, data['mac'], reset_arp=False) # Change the MAC address and try again, leading to reset of ARP. data['mac'] = stub_utils.get_mac() with mock.patch('calico.felix.devices.set_routes'): with mock.patch('calico.felix.devices.configure_interface_ipv4'): local_ep.on_endpoint_update(data, async=False) self.assertEqual(local_ep._mac, data['mac']) devices.configure_interface_ipv4.assert_called_once_with(iface) devices.set_routes.assert_called_once_with(ip_type, set(ips), iface, data['mac'], reset_arp=True) # Send empty data, which deletes the endpoint. with mock.patch('calico.felix.devices.set_routes'): local_ep.on_endpoint_update(None, async=False) devices.set_routes.assert_called_once_with(ip_type, set(), data["name"], None)
def test_on_endpoint_update_v6(self): combined_id = EndpointId("host_id", "orchestrator_id", "workload_id", "endpoint_id") ip_type = futils.IPV6 retcode = futils.CommandOutput("", "") local_ep = self.get_local_endpoint(combined_id, ip_type) # Call with no data; should be ignored (no configuration to remove). local_ep.on_endpoint_update(None, async=False) ips = ["2001::abcd"] gway = "2020:ab::9876" iface = "tapabcdef" data = { 'endpoint': "endpoint_id", 'mac': stub_utils.get_mac(), 'name': iface, 'ipv6_nets': ips, 'ipv6_gateway': gway, 'profile_ids': []} # Report an initial update (endpoint creation) and check configured with mock.patch('calico.felix.devices.set_routes'): with mock.patch('calico.felix.devices.configure_interface_ipv6'): local_ep.on_endpoint_update(data, async=False) self.assertEqual(local_ep._mac, data['mac']) devices.configure_interface_ipv6.assert_called_once_with(iface, gway) devices.set_routes.assert_called_once_with(ip_type, set(ips), iface, data['mac'], reset_arp=False) # Send through an update with no changes - should redo without # resetting ARP. with mock.patch('calico.felix.devices.set_routes'): with mock.patch('calico.felix.devices.configure_interface_ipv6'): local_ep.on_endpoint_update(data, async=False) self.assertEqual(local_ep._mac, data['mac']) devices.configure_interface_ipv6.assert_called_once_with(iface, gway) devices.set_routes.assert_called_once_with(ip_type, set(ips), iface, data['mac'], reset_arp=False) # Send through an update with no changes - would reset ARP, but this is # IPv6 so it won't. data['mac'] = stub_utils.get_mac() with mock.patch('calico.felix.devices.set_routes'): with mock.patch('calico.felix.devices.configure_interface_ipv6'): local_ep.on_endpoint_update(data, async=False) self.assertEqual(local_ep._mac, data['mac']) devices.configure_interface_ipv6.assert_called_once_with(iface, gway) devices.set_routes.assert_called_once_with(ip_type, set(ips), iface, data['mac'], reset_arp=False) # Send empty data, which deletes the endpoint. with mock.patch('calico.felix.devices.set_routes'): local_ep.on_endpoint_update(None, async=False) devices.set_routes.assert_called_once_with(ip_type, set(), data["name"], None)