Example #1
0
    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::"]))
Example #2
0
    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")},
            }
        )
Example #3
0
    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"])
Example #5
0
    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)
Example #6
0
    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, [])
Example #7
0
    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"])
Example #9
0
 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)
Example #10
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())
Example #11
0
    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)
Example #12
0
    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])
Example #13
0
    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)
Example #14
0
 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)
Example #15
0
 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")]))
Example #16
0
    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)
Example #17
0
    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)
Example #18
0
    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)