Esempio n. 1
0
    def _configure_interface(self, mac_changed=True):
        """
        Applies sysctls and routes to the interface.

        :param: bool mac_changed: Has the MAC address changed since it was last
                     configured? If so, we reconfigure ARP for the interface in
                     IPv4 (ARP does not exist for IPv6, which uses neighbour
                     solicitation instead).
        """
        try:
            if self.ip_type == IPV4:
                devices.configure_interface_ipv4(self._iface_name)
                reset_arp = mac_changed
            else:
                ipv6_gw = self.endpoint.get("ipv6_gateway", None)
                devices.configure_interface_ipv6(self._iface_name, ipv6_gw)
                reset_arp = False

            ips = set()
            for ip in self.endpoint.get(self.nets_key, []):
                ips.add(futils.net_to_ip(ip))
            devices.set_routes(self.ip_type, ips, self._iface_name, self.endpoint["mac"], reset_arp=reset_arp)

        except (IOError, FailedSystemCall):
            if not devices.interface_exists(self._iface_name):
                _log.info("Interface %s for %s does not exist yet", self._iface_name, self.combined_id)
            elif not devices.interface_up(self._iface_name):
                _log.info("Interface %s for %s is not up yet", self._iface_name, self.combined_id)
            else:
                # Interface flapped back up after we failed?
                _log.warning("Failed to configure interface %s for %s", self._iface_name, self.combined_id)
Esempio n. 2
0
 def _deconfigure_interface(self):
     """
     Removes routes from the interface.
     """
     try:
         devices.set_routes(self.ip_type, set(), self._iface_name, None)
     except FailedSystemCall as e:
         if "Cannot find device" in e.stderr:
             # Deleted under our feet - so the rules are gone.
             _log.info("Interface %s for %s already deleted",
                       self._iface_name, self.combined_id)
         else:
             # Since there are lots of potential races here with trying to
             # check status and interfaces flapping, log and continue.
             _log.exception(
                 "Failed to remove routes from interface %s "
                 "for %s, but interface appears to still be "
                 "present. Assuming the interface flapped.",
                 self._iface_name, self.combined_id)
     except IOError:
         if not devices.interface_exists(self._iface_name):
             # Deleted under our feet - so the rules are gone.
             _log.info("Interface %s for %s already deleted",
                       self._iface_name, self.combined_id)
         else:
             # Since there are lots of potential races here with trying to
             # check status and interfaces flapping, log and continue.
             _log.exception(
                 "Failed to remove routes from interface %s "
                 "for %s, but interface appears to still be "
                 "present. Assuming the interface flapped.",
                 self._iface_name, self.combined_id)
     else:
         _log.info("Interface %s deconfigured", self._iface_name)
         super(WorkloadEndpoint, self)._deconfigure_interface()
Esempio n. 3
0
 def test_set_routes_mac_required(self):
     type = futils.IPV4
     ips = set(["1.2.3.4", "2.3.4.5"])
     interface = "tapabcdef"
     mac = stub_utils.get_mac()
     with self.assertRaisesRegexp(ValueError, "mac must be supplied if ips is not " "empty"):
         devices.set_routes(type, ips, interface)
Esempio n. 4
0
 def test_set_routes_arp_ipv4_only(self):
     type = futils.IPV4
     ips = set(["1.2.3.4", "2.3.4.5"])
     interface = "tapabcdef"
     mac = stub_utils.get_mac()
     with self.assertRaisesRegexp(ValueError, "reset_arp may only be supplied for " "IPv4"):
         devices.set_routes(futils.IPV6, ips, interface, mac=mac, reset_arp=True)
Esempio n. 5
0
    def _configure_interface(self):
        """
        Applies sysctls and routes to the interface.
        """
        try:
            if self.ip_type == IPV4:
                devices.configure_interface_ipv4(self._iface_name)
                nets_key = "ipv4_nets"
            else:
                ipv6_gw = self.endpoint.get("ipv6_gateway", None)
                devices.configure_interface_ipv6(self._iface_name, ipv6_gw)
                nets_key = "ipv6_nets"

            ips = set()
            for ip in self.endpoint.get(nets_key, []):
                ips.add(futils.net_to_ip(ip))
            devices.set_routes(self.ip_type, ips, self._iface_name,
                               self.endpoint["mac"])

        except (IOError, FailedSystemCall, CalledProcessError):
            if not devices.interface_exists(self._iface_name):
                _log.info("Interface %s for %s does not exist yet",
                          self._iface_name, self.endpoint_id)
            elif not devices.interface_up(self._iface_name):
                _log.info("Interface %s for %s is not up yet",
                          self._iface_name, self.endpoint_id)
            else:
                # OK, that really should not happen.
                _log.exception("Failed to configure interface %s for %s",
                               self._iface_name, self.endpoint_id)
                raise
Esempio n. 6
0
    def _configure_interface(self):
        """
        Applies sysctls and routes to the interface.
        """
        try:
            if self.ip_type == IPV4:
                devices.configure_interface_ipv4(self._iface_name)
                nets_key = "ipv4_nets"
            else:
                ipv6_gw = self.endpoint.get("ipv6_gateway", None)
                devices.configure_interface_ipv6(self._iface_name, ipv6_gw)
                nets_key = "ipv6_nets"

            ips = set()
            for ip in self.endpoint.get(nets_key, []):
                ips.add(futils.net_to_ip(ip))
            devices.set_routes(self.ip_type, ips,
                               self._iface_name,
                               self.endpoint["mac"])

        except (IOError, FailedSystemCall, CalledProcessError):
            if not devices.interface_exists(self._iface_name):
                _log.info("Interface %s for %s does not exist yet",
                          self._iface_name, self.endpoint_id)
            elif not devices.interface_up(self._iface_name):
                _log.info("Interface %s for %s is not up yet",
                          self._iface_name, self.endpoint_id)
            else:
                # Interface flapped back up after we failed?
                _log.warning("Failed to configure interface %s for %s",
                             self._iface_name, self.endpoint_id)
Esempio n. 7
0
 def test_set_routes_mac_required(self):
     type = futils.IPV4
     ips = set(["1.2.3.4", "2.3.4.5"])
     interface = "tapabcdef"
     mac = stub_utils.get_mac()
     with self.assertRaisesRegexp(ValueError,
                                  "mac must be supplied if ips is not "
                                  "empty"):
         devices.set_routes(type, ips, interface)
Esempio n. 8
0
 def test_set_routes_arp_ipv4_only(self):
     type = futils.IPV4
     ips = set(["1.2.3.4", "2.3.4.5"])
     interface = "tapabcdef"
     mac = stub_utils.get_mac()
     with self.assertRaisesRegexp(ValueError,
                                  "reset_arp may only be supplied for "
                                  "IPv4"):
         devices.set_routes(futils.IPV6, ips, interface, mac=mac,
                            reset_arp=True)
Esempio n. 9
0
 def test_set_routes_nothing_to_do(self, m_remove_conntrack):
     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_ips", return_value=ips):
             devices.set_routes(type, ips, interface, mac)
             self.assertEqual(futils.check_call.call_count, 0)
             m_remove_conntrack.assert_called_once_with(set(), 4)
Esempio n. 10
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)
Esempio n. 11
0
 def _deconfigure_interface(self):
     """
     Removes routes from the interface.
     """
     try:
         devices.set_routes(self.ip_type, set(), self._iface_name, None)
     except (IOError, FailedSystemCall):
         if not devices.interface_exists(self._iface_name):
             # Deleted under our feet - so the rules are gone.
             _log.debug("Interface %s for %s deleted", self._iface_name, self.combined_id)
         else:
             # An error deleting the rules. Log and continue.
             _log.exception("Cannot delete rules for interface %s for %s", self._iface_name, self.combined_id)
Esempio n. 12
0
    def _configure_interface(self):
        """
        Applies sysctls and routes to the interface.
        """
        if not self._device_is_up:
            _log.debug("Device is known to be down, skipping attempt to "
                       "configure it.")
            return
        try:
            if self.ip_type == IPV4:
                devices.configure_interface_ipv4(self._iface_name)
                reset_arp = self._mac_changed
            else:
                ipv6_gw = self.endpoint.get("ipv6_gateway", None)
                devices.configure_interface_ipv6(self._iface_name, ipv6_gw)
                reset_arp = False

            ips = set()
            for ip in self.endpoint.get(self.nets_key, []):
                ips.add(futils.net_to_ip(ip))
            for nat_map in self.endpoint.get(nat_key(self.ip_type), []):
                ips.add(nat_map['ext_ip'])
            devices.set_routes(self.ip_type,
                               ips,
                               self._iface_name,
                               self.endpoint.get("mac"),
                               reset_arp=reset_arp)

        except (IOError, FailedSystemCall) as e:
            if not devices.interface_exists(self._iface_name):
                _log.info("Interface %s for %s does not exist yet",
                          self._iface_name, self.combined_id)
            elif not devices.interface_up(self._iface_name):
                _log.info("Interface %s for %s is not up yet",
                          self._iface_name, self.combined_id)
            else:
                # Either the interface flapped back up after the failure (in
                # which case we'll retry when the event reaches us) or there
                # was a genuine failure due to bad data or some other factor.
                #
                # Since the former is fairly common, we log at warning level
                # rather than error, which avoids false positives.
                _log.warning(
                    "Failed to configure interface %s for %s: %r.  "
                    "Either the interface is flapping or it is "
                    "misconfigured.", self._iface_name, self.combined_id, e)
        else:
            _log.info("Interface %s configured", self._iface_name)
            super(WorkloadEndpoint, self)._configure_interface()
Esempio n. 13
0
 def _deconfigure_interface(self):
     """
     Removes routes from the interface.
     """
     try:
         devices.set_routes(self.ip_type, set(), self._iface_name, None)
     except (IOError, FailedSystemCall):
         if not devices.interface_exists(self._iface_name):
             # Deleted under our feet - so the rules are gone.
             _log.debug("Interface %s for %s deleted", self._iface_name,
                        self.combined_id)
         else:
             # An error deleting the rules. Log and continue.
             _log.exception("Cannot delete rules for interface %s for %s",
                            self._iface_name, self.combined_id)
Esempio n. 14
0
    def _configure_interface(self):
        """
        Applies sysctls and routes to the interface.
        """
        if not self._device_is_up:
            _log.debug("Device is known to be down, skipping attempt to "
                       "configure it.")
            return
        try:
            if self.ip_type == IPV4:
                devices.configure_interface_ipv4(self._iface_name)
                reset_arp = self._mac_changed
            else:
                ipv6_gw = self.endpoint.get("ipv6_gateway", None)
                devices.configure_interface_ipv6(self._iface_name, ipv6_gw)
                reset_arp = False

            ips = set()
            for ip in self.endpoint.get(self.nets_key, []):
                ips.add(futils.net_to_ip(ip))
            for nat_map in self.endpoint.get(nat_key(self.ip_type), []):
                ips.add(nat_map['ext_ip'])
            devices.set_routes(self.ip_type, ips,
                               self._iface_name,
                               self.endpoint["mac"],
                               reset_arp=reset_arp)

        except (IOError, FailedSystemCall) as e:
            if not devices.interface_exists(self._iface_name):
                _log.info("Interface %s for %s does not exist yet",
                          self._iface_name, self.combined_id)
            elif not devices.interface_up(self._iface_name):
                _log.info("Interface %s for %s is not up yet",
                          self._iface_name, self.combined_id)
            else:
                # Either the interface flapped back up after the failure (in
                # which case we'll retry when the event reaches us) or there
                # was a genuine failure due to bad data or some other factor.
                #
                # Since the former is fairly common, we log at warning level
                # rather than error, which avoids false positives.
                _log.warning("Failed to configure interface %s for %s: %r.  "
                             "Either the interface is flapping or it is "
                             "misconfigured.", self._iface_name,
                             self.combined_id, e)
        else:
            _log.info("Interface %s configured", self._iface_name)
            self._device_in_sync = True
Esempio n. 15
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)
Esempio n. 16
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)
Esempio n. 17
0
    def test_set_routes_mainline(self, m_remove_conntrack):
        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_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)
                m_remove_conntrack.assert_called_once_with(set(), 4)
Esempio n. 18
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_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)
Esempio n. 19
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)
Esempio n. 20
0
    def _configure_interface(self):
        """
        Applies sysctls and routes to the interface.

        :param: bool mac_changed: Has the MAC address changed since it was last
                     configured? If so, we reconfigure ARP for the interface in
                     IPv4 (ARP does not exist for IPv6, which uses neighbour
                     solicitation instead).
        """
        try:
            if self.ip_type == IPV4:
                devices.configure_interface_ipv4(self._iface_name)
                reset_arp = self._mac_changed
            else:
                ipv6_gw = self.endpoint.get("ipv6_gateway", None)
                devices.configure_interface_ipv6(self._iface_name, ipv6_gw)
                reset_arp = False

            ips = set()
            for ip in self.endpoint.get(self.nets_key, []):
                ips.add(futils.net_to_ip(ip))
            devices.set_routes(self.ip_type,
                               ips,
                               self._iface_name,
                               self.endpoint["mac"],
                               reset_arp=reset_arp)

        except (IOError, FailedSystemCall):
            if not devices.interface_exists(self._iface_name):
                _log.info("Interface %s for %s does not exist yet",
                          self._iface_name, self.combined_id)
            elif not devices.interface_up(self._iface_name):
                _log.info("Interface %s for %s is not up yet",
                          self._iface_name, self.combined_id)
            else:
                # Interface flapped back up after we failed?
                _log.warning("Failed to configure interface %s for %s",
                             self._iface_name, self.combined_id)
        else:
            _log.info("Interface %s configured", self._iface_name)
            self._device_in_sync = True
            self._device_has_been_in_sync = True
Esempio n. 21
0
 def test_set_routes_mac_not_set(self):
     type = futils.IPV4
     ips = set(["1.2.3.4", "2.3.4.5"])
     interface = "tapabcdef"
     with mock.patch("calico.felix.futils.check_call") as m_check_call:
         devices.set_routes(type, ips, interface)
Esempio n. 22
0
 def test_set_routes_mac_not_set(self):
     type = futils.IPV4
     ips = set(["1.2.3.4", "2.3.4.5"])
     interface = "tapabcdef"
     with mock.patch("calico.felix.futils.check_call") as m_check_call:
         devices.set_routes(type, ips, interface)