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)
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
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)
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()
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
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
def _apply_endpoint_update(self): pending_endpoint = self._pending_endpoint if pending_endpoint == self.endpoint: _log.debug("Endpoint hasn't changed, nothing to do") return # Calculate the set of IPs that we had before this update. Needed on # the update and delete code paths below. if self.endpoint: old_ips = set(futils.net_to_ip(n) for n in self.endpoint.get(self.nets_key, [])) old_nat_mappings = self.endpoint.get(self.nat_key, []) else: old_ips = set() old_nat_mappings = [] all_old_ips = old_ips | set([n["ext_ip"] for n in old_nat_mappings]) if pending_endpoint: # Update/create. if pending_endpoint['mac'] != self._mac: # Either we have not seen this MAC before, or it has changed. _log.debug("Endpoint MAC changed to %s", pending_endpoint["mac"]) self._mac = pending_endpoint['mac'] self._mac_changed = True # MAC change requires refresh of iptables rules and ARP table. self._iptables_in_sync = False self._device_in_sync = False if self.endpoint is None: # This is the first time we have seen the endpoint, so extract # the interface name and endpoint ID. self._iface_name = pending_endpoint["name"] self._suffix = interface_to_suffix(self.config, self._iface_name) _log.debug("Learned interface name/suffix: %s/%s", self._iface_name, self._suffix) # First time through, need to program everything. self._iptables_in_sync = False self._device_in_sync = False if self._device_is_up is None: _log.debug("Learned interface name, checking if device " "is up.") self._device_is_up = ( devices.interface_exists(self._iface_name) and devices.interface_up(self._iface_name) ) # Check if the profile ID or IP addresses have changed, requiring # a refresh of the dataplane. profile_ids = set(pending_endpoint.get("profile_ids", [])) if profile_ids != self._explicit_profile_ids: # Profile ID update requires iptables update but not device # update. _log.debug("Profile IDs changed from %s to %s, need to update " "iptables", self._rules_ref_helper.required_refs, profile_ids) self._explicit_profile_ids = profile_ids self._iptables_in_sync = False self._profile_ids_dirty = True # Check for changes to values that require a device update. if self.endpoint: if self.endpoint.get("state") != pending_endpoint.get("state"): _log.debug("Desired interface state updated.") self._device_in_sync = False self._iptables_in_sync = False new_ips = set(futils.net_to_ip(n) for n in pending_endpoint.get(self.nets_key, [])) if old_ips != new_ips: # IP addresses have changed, need to update the routing # table. _log.debug("IP addresses changed, need to update routing") self._device_in_sync = False new_nat_mappings = pending_endpoint.get(self.nat_key, []) if old_nat_mappings != new_nat_mappings: _log.debug("NAT mappings have changed, refreshing.") self._device_in_sync = False self._iptables_in_sync = False all_new_ips = new_ips | set([n["ext_ip"] for n in new_nat_mappings]) if all_old_ips != all_new_ips: # Ensure we clean up any conntrack entries for IPs that # have been removed. _log.debug("Set of all IPs changed from %s to %s", all_old_ips, all_new_ips) self._removed_ips |= all_old_ips self._removed_ips -= all_new_ips else: # Delete of the endpoint. Need to resync everything. self._profile_ids_dirty = True self._iptables_in_sync = False self._device_in_sync = False self._removed_ips |= all_old_ips self.endpoint = pending_endpoint self._endpoint_update_pending = False self._pending_endpoint = None
def _apply_endpoint_update(self): pending_endpoint = self._pending_endpoint if pending_endpoint == self.endpoint: _log.debug("Endpoint hasn't changed, nothing to do") return # Calculate the set of IPs that we had before this update. Needed on # the update and delete code paths below. if self.endpoint: old_ips = set( futils.net_to_ip(n) for n in self.endpoint.get(self.nets_key, [])) old_nat_mappings = self.endpoint.get(self.nat_key, []) else: old_ips = set() old_nat_mappings = [] all_old_ips = old_ips | set([n["ext_ip"] for n in old_nat_mappings]) if pending_endpoint: # Update/create. if pending_endpoint.get('mac') != self._mac: # Either we have not seen this MAC before, or it has changed. _log.debug("Endpoint MAC changed to %s", pending_endpoint.get("mac")) self._mac = pending_endpoint.get('mac') self._mac_changed = True # MAC change requires refresh of iptables rules and ARP table. self._iptables_in_sync = False self._device_in_sync = False new_iface_name = pending_endpoint["name"] # Interface renames are handled in the EndpointManager by # simulating a delete then an add. We shouldn't see one here. assert (self.endpoint is None or self._iface_name == new_iface_name), ( "Unexpected change of interface name.") if self.endpoint is None: # This is the first time we have seen the endpoint, so extract # the interface name and endpoint ID. self._iface_name = new_iface_name self._suffix = interface_to_chain_suffix( self.config, self._iface_name) _log.debug("Learned interface name/suffix: %s/%s", self._iface_name, self._suffix) # First time through, need to program everything. self._iptables_in_sync = False self._device_in_sync = False if self._device_is_up is None: _log.debug("Learned interface name, checking if device " "is up.") self._device_is_up = ( devices.interface_exists(self._iface_name) and devices.interface_up(self._iface_name)) # Check if the profile ID or IP addresses have changed, requiring # a refresh of the dataplane. profile_ids = set(pending_endpoint.get("profile_ids", [])) if profile_ids != self._explicit_profile_ids: # Profile ID update requires iptables update but not device # update. _log.debug( "Profile IDs changed from %s to %s, need to update " "iptables", self._rules_ref_helper.required_refs, profile_ids) self._explicit_profile_ids = profile_ids self._iptables_in_sync = False self._profile_ids_dirty = True # Check for changes to values that require a device update. if self.endpoint: if self.endpoint.get("state") != pending_endpoint.get("state"): _log.debug("Desired interface state updated.") self._device_in_sync = False self._iptables_in_sync = False new_ips = set( futils.net_to_ip(n) for n in pending_endpoint.get(self.nets_key, [])) if old_ips != new_ips: # IP addresses have changed, need to update the routing # table. _log.debug("IP addresses changed, need to update routing") self._device_in_sync = False new_nat_mappings = pending_endpoint.get(self.nat_key, []) if old_nat_mappings != new_nat_mappings: _log.debug("NAT mappings have changed, refreshing.") self._device_in_sync = False self._iptables_in_sync = False all_new_ips = new_ips | set( [n["ext_ip"] for n in new_nat_mappings]) if all_old_ips != all_new_ips: # Ensure we clean up any conntrack entries for IPs that # have been removed. _log.debug("Set of all IPs changed from %s to %s", all_old_ips, all_new_ips) self._removed_ips |= all_old_ips self._removed_ips -= all_new_ips else: # Delete of the endpoint. Need to resync everything. self._profile_ids_dirty = True self._iptables_in_sync = False self._device_in_sync = False self._removed_ips |= all_old_ips self.endpoint = pending_endpoint self._endpoint_update_pending = False self._pending_endpoint = None